安卓竖屏转横屏时Fragment内RecyclerView数据重复问题求助
这个问题我太熟悉了!本质原因是横竖屏切换时Activity重建,导致Fragment被重复添加,容器里存在多个Fragment实例,每个都带着自己的RecyclerView,所以会看到重复数据和滑动后出现的另一个列表。
核心原因分析
Android默认在横竖屏切换时会销毁当前Activity并重建它,同时FragmentManager会自动保存并恢复之前的Fragment实例。如果你的onCreate方法里没有判断,每次都重新添加一个新的Fragment到容器里,就会出现「旧Fragment没被移除,新Fragment又加进来」的情况,两个Fragment叠在一起,自然会看到两个RecyclerView。
解决方案1:避免重复添加Fragment(推荐)
修改你的DailyAzkaar的onCreate方法,在添加Fragment前先判断savedInstanceState是否为null——只有第一次创建Activity时(savedInstanceState为null)才添加Fragment,重建时(savedInstanceState不为null)跳过这一步,因为FragmentManager已经帮你恢复了之前的Fragment。
示例代码修改:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_daily_azkaar); // 其他初始化代码(Toolbar、SharedPreferences等) toolbar = findViewById(R.id.toolbar); settings = getSharedPreferences("MyPrefs", MODE_PRIVATE); locale = settings.getString("locale", "ar"); // 关键:添加Fragment前判断savedInstanceState if (savedInstanceState == null) { // 替换成你的Fragment类名 YourAzkaarFragment fragment = new YourAzkaarFragment(); getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, fragment) // 替换成你的容器ID .commit(); } }
解决方案2:用ViewModel保存Fragment数据(可选,增强稳定性)
如果你的Fragment里是在onCreateView或onViewCreated里加载RecyclerView数据,横竖屏重建时可能会重新请求数据导致重复加载。可以用ViewModel来保存数据,确保配置变化时数据不会丢失或重复加载:
在你的Fragment里定义ViewModel:
public class YourAzkaarFragment extends Fragment { private AzkaarViewModel viewModel; private RecyclerView recyclerView; private AzkaarAdapter adapter; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_azkaar, container, false); recyclerView = view.findViewById(R.id.recycler_view); adapter = new AzkaarAdapter(); recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); // 初始化ViewModel viewModel = new ViewModelProvider(this).get(AzkaarViewModel.class); // 观察数据变化,只在数据更新时刷新Adapter viewModel.getAzkaarList().observe(getViewLifecycleOwner(), azkaarList -> { adapter.submitList(azkaarList); }); return view; } } // ViewModel类 public class AzkaarViewModel extends ViewModel { private MutableLiveData<List<AzkaarItem>> azkaarList; public MutableLiveData<List<AzkaarItem>> getAzkaarList() { if (azkaarList == null) { azkaarList = new MutableLiveData<>(); loadAzkaarData(); // 这里是你的数据加载逻辑(从本地或网络) } return azkaarList; } private void loadAzkaarData() { // 加载数据并设置到azkaarList List<AzkaarItem> data = ...; azkaarList.setValue(data); } }
不推荐的方案:禁止Activity重建
你也可以在AndroidManifest.xml里给DailyAzkaar添加configChanges属性,让系统不重建Activity,但这种方法会跳过系统的资源适配(比如横屏布局的加载),除非你自己手动处理所有配置变化,否则不建议使用:
<activity android:name=".DailyAzkaar" android:configChanges="orientation|screenSize|smallestScreenSize"> </activity>
按照上面的方法修改后,横屏切换时就不会再出现RecyclerView重复的问题啦!
内容的提问来源于stack exchange,提问作者Noura Ali

