安卓在我旋转屏幕后显示了两个RecyclerView。

huangapple go评论69阅读模式
英文:

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:

安卓在我旋转屏幕后显示了两个RecyclerView。

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&lt;Crime&gt; 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(&quot;Position&quot;,-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:

&lt;activity android:configChanges=&quot;orientation|screenSize&quot;&gt;
       
&lt;/activity&gt;

This prevents the OS from recreating the activity at rotation, which leads in issues like yours.

huangapple
  • 本文由 发表于 2020年10月3日 20:18:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/64184168.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定