Activity中Fragment屏幕旋转刷新异常问题求助(抽屉布局场景)
Hey there, I’ve run into this exact problem multiple times when building apps with DrawerLayout and Fragments—screen rotation causing weird Fragment refresh glitches, duplicate instances, or lost state. Let’s walk through the solutions that consistently work:
1. Stop Re-Adding Fragments on Activity Re-Creation
The biggest culprit here is that Android automatically destroys and recreates your Activity on screen rotation. By default, it also restores the last Fragment instance for you. If you’re still manually adding the default Fragment in onCreate() every time, you’ll end up with duplicate Fragments or state conflicts.
Fix this by checking if savedInstanceState is null before loading your initial Fragment:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Only load the default Fragment if this is the first launch (not a rotation) if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .replace(R.id.fragment_container, new FirstFragment()) .commit(); } }
This way, when the Activity is recreated after rotation, you let the system restore the existing Fragment instead of adding a new one.
2. Properly Save and Restore Fragment State
Even if the Fragment is restored, its UI state (like selected list items, input text, or scroll positions) might get lost. Override onSaveInstanceState() in your Fragments to preserve critical state, then restore it when the Fragment is recreated:
// Inside your Fragment @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); // Save your UI state here (e.g., selected tab position, scroll offset) outState.putInt("selected_tab", mSelectedTabIndex); outState.putParcelable("scroll_position", mRecyclerView.getLayoutManager().onSaveInstanceState()); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); if (savedInstanceState != null) { // Restore the saved state mSelectedTabIndex = savedInstanceState.getInt("selected_tab"); Parcelable scrollState = savedInstanceState.getParcelable("scroll_position"); mRecyclerView.getLayoutManager().onRestoreInstanceState(scrollState); } }
This ensures your Fragment’s UI picks up right where it left off after rotation.
3. Use ViewModel for Persistent Data
If your Fragment relies on data that takes time to load (like network responses or database queries), using a ViewModel will keep that data alive through screen rotations. ViewModels aren’t destroyed when the Activity/Fragment is recreated, so you don’t have to re-fetch data every time the screen rotates:
// Create a ViewModel class for your Fragment public class MyFragmentViewModel extends ViewModel { private final MutableLiveData<List<MyData>> mData = new MutableLiveData<>(); private boolean mIsDataLoaded = false; public LiveData<List<MyData>> getData() { return mData; } public void loadData() { if (!mIsDataLoaded) { // Simulate a network call or database query ApiService.fetchData(new Callback<List<MyData>>() { @Override public void onSuccess(List<MyData> data) { mData.setValue(data); mIsDataLoaded = true; } }); } } }
Then in your Fragment:
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); MyFragmentViewModel viewModel = new ViewModelProvider(this).get(MyFragmentViewModel.class); viewModel.getData().observe(getViewLifecycleOwner(), data -> { // Update your UI with the data updateRecyclerView(data); }); // Load data only if it hasn't been loaded yet viewModel.loadData(); }
This eliminates redundant data fetching and keeps your UI consistent across rotations.
4. Optional: Disable Activity Re-Creation (Use With Caution)
If you want to avoid the Activity re-creation entirely, you can add configChanges to your Activity in the AndroidManifest.xml. This tells Android to not destroy the Activity on rotation, and instead call onConfigurationChanged():
<activity android:name=".MainActivity" android:configChanges="orientation|screenSize"> </activity>
Then handle the layout change manually in your Activity:
@Override public void onConfigurationChanged(@NonNull Configuration newConfig) { super.onConfigurationChanged(newConfig); // Re-set the content view to load the landscape/portrait layout setContentView(R.layout.activity_main); // Update your current Fragment's UI if needed Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container); if (currentFragment != null) { ((ConfigurableFragment) currentFragment).onConfigurationChanged(newConfig); } }
Note: This approach requires more manual work to handle layout changes and state sync, so only use it if the first three solutions don’t fit your use case.
内容的提问来源于stack exchange,提问作者Farrukh khalid

