英文:
Android displays two recyclerViews after I rotate the screen
问题
我在FrameLayout中保留了一个片段。在片段中,我使用了一个回收站视图(Recycler View)。它工作得很好,唯一的问题是,当我旋转手机时,我会看到两个回收站视图,一个在另一个上面(尽管第二个回收站只是在背景中,就像一张图片,我既不能滚动它,也不能点击它的项)。它仍然可以正常工作,我可以毫无问题地操作新的回收站视图。但是当我向下滚动时会出现以下情况:
[![在这里输入图片描述][1]][1]
CrimeListFragment类中包含了回收站视图:
public class CrimeListFragment extends Fragment {
private FragmentCrimeLabBinding binding;
private static final int REQUEST_CRIME = 1;
private RecyclerView.Adapter mAdapter;
private int position;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView (LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentCrimeLabBinding.inflate(inflater, container, false);
View view = binding.getRoot();
binding.rvCrimeList.setLayoutManager(new LinearLayoutManager(view.getContext()));
binding.rvCrimeList.hasFixedSize();
mAdapter = new MyAdapter(CrimeLab.getInstance(getActivity()).getCrimes(), getActivity());
binding.rvCrimeList.setAdapter(mAdapter);
return view;
}
@Override
public void onResume() {
updateUI();
super.onResume();
}
private void updateUI() {
CrimeLab crimeLab = CrimeLab.getInstance(getActivity());
List<Crime> crimes = crimeLab.getCrimes();
if (mAdapter == null) {
mAdapter = new MyAdapter(crimes,getActivity());
binding.rvCrimeList.setAdapter(mAdapter);
} else {
mAdapter.notifyDataSetChanged();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if(requestCode == REQUEST_CRIME) {
if(resultCode == Activity.RESULT_OK) {
position = data.getIntExtra("Position",-1);
updateUI();
}
}
}
}
CrimeListActivity类包含了这个片段:
public class CrimeListActivity extends AppCompatActivity {
ActivityCrimeLabBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityCrimeLabBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.add(R.id.frame_layout, new CrimeListFragment()).commit();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
}
更新:我在发布问题后立即找到了解决方案。
在Activity的onCreate()中,我调用了fragmentTransaction.add()方法。相反,我调用了.replace()方法,现在它按照我期望的方式工作。
但问题仍未解决,因为我不知道为什么会这样工作。为什么我的片段在默认情况下在旋转后没有被移除?为什么我需要调用像detach()或replace()这样的方法?这与活动不同(例如,当我们旋转屏幕时,活动会被Android完全销毁)
英文:
I keep a fragment in a FrameLayout. In the fragment I use recycler view. It works fine, the only thing is that when I rotate the phone I see two recycler views, one on another (The second recycler is just in the background though, it's like a picture and I can neither scroll it, nor to click on its items). It still works fine, I can manipulate the new recycler with no problem. But this is what happens when I scroll down:
CrimeListFragment.class which contains the Recycler:
public class CrimeListFragment extends Fragment {
private FragmentCrimeLabBinding binding;
private static final int REQUEST_CRIME = 1;
private RecyclerView.Adapter mAdapter;
private int position;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView (LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentCrimeLabBinding.inflate(inflater, container, false);
View view = binding.getRoot();
binding.rvCrimeList.setLayoutManager(new LinearLayoutManager(view.getContext()));
binding.rvCrimeList.hasFixedSize();
mAdapter = new MyAdapter(CrimeLab.getInstance(getActivity()).getCrimes(), getActivity());
binding.rvCrimeList.setAdapter(mAdapter);
return view;
}
@Override
public void onResume() {
updateUI();
super.onResume();
}
private void updateUI() {
CrimeLab crimeLab = CrimeLab.getInstance(getActivity());
List<Crime> crimes = crimeLab.getCrimes();
if (mAdapter == null) {
mAdapter = new MyAdapter(crimes,getActivity());
binding.rvCrimeList.setAdapter(mAdapter);
} else {
mAdapter.notifyDataSetChanged();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if(requestCode == REQUEST_CRIME) {
if(resultCode == Activity.RESULT_OK) {
position = data.getIntExtra("Position",-1);
updateUI();
}
}
}
}
CrimeListActivity contains the fragment:
public class CrimeListActivity extends AppCompatActivity {
ActivityCrimeLabBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityCrimeLabBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.add(R.id.frame_layout, new CrimeListFragment()).commit();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
}
UPD: I found the solution right after I published the question.
In the Activity.onCreate() I called fragmentTransaction.add() method. Instead, I call .replace() and now it works as I expect.
But the question is still not resolved, because I have no idea why it works like this. Why my fragment is not removed after rotation by default? Why should I call methods such as detach() or replace()? It differs with activities (e.g. when we rotate the screen, an activity is destroyed by android altogether )
答案1
得分: 2
旋转设备会触发配置更改,并重新创建您的活动。如果不检查保存的状态是否为 null,则最终会添加多个片段。将您的代码更改为以下内容:
if (savedInstanceState == null) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.add(R.id.frame_layout, new CrimeListFragment()).commit();
}
英文:
Rotating the device triggers a configuration change and your activity is recreated. By not checking if saved state is null, you end up adding multiple fragments. Change your code to this:
if (savedInstanceState == null){
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction =
fm.beginTransaction();
transaction.add(R.id.frame_layout, new
CrimeListFragment()).commit();}
答案2
得分: 1
将以下内容添加到您定义活动的清单中:
<activity android:configChanges="orientation|screenSize">
</activity>
这将阻止操作系统在旋转时重新创建活动,从而避免了类似您遇到的问题。
英文:
Add this line to your manifest, where you define your activity:
<activity android:configChanges="orientation|screenSize">
</activity>
This prevents the OS from recreating the activity at rotation, which leads in issues like yours.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论