Android Navigation Component跳转Activity返回重复加载Fragment且汉堡图标失效
问题解决方案
根因分析
- 导航逻辑错误:HomeFragment跳转DetailsActivity时使用
setPopUpTo(R.id.nav_home, true)将当前HomeFragment从NavController回退栈中弹出,导致从DetailsActivity返回时回退栈为空,NavController会重新创建HomeFragment实例,看起来像是回到了同一个页面 - MutableLiveData粘性问题:普通MutableLiveData会保存历史数据,新创建的HomeFragment订阅时会收到旧的列表数据,进一步强化了“回到同一页面”的感知
- MainActivity变量作用域错误:将ViewBinding定义为onCreate方法的局部变量,导致Activity重建后AppBarConfiguration持有的DrawerLayout引用失效,汉堡图标点击无法触发抽屉打开逻辑
修复步骤
1. 修正HomeFragment导航逻辑
移除多余的setPopUpTo配置,跳转DetailsActivity时不需要弹出当前HomeFragment:
// 修改前 Navigation.findNavController(requireView()) .navigate(R.id.detailsActivity, bundle, new NavOptions.Builder() .setPopUpTo(R.id.nav_home, true).build() ); // 修改后 Navigation.findNavController(requireView()) .navigate(R.id.detailsActivity, bundle);
2. 处理MutableLiveData粘性事件
使用事件包装类包裹需要单次消费的数据,避免新Fragment实例收到旧的已处理数据:
首先创建Event通用包装类:
public class Event<T> { private T content; private boolean hasBeenHandled = false; public Event(T content) { this.content = content; } // 仅当事件未被消费时返回数据 public T getContentIfNotHandled() { if (hasBeenHandled) { return null; } hasBeenHandled = true; return content; } // 强制读取数据,不修改消费状态 public T peekContent() { return content; } }
然后修改ViewModel中的LiveData定义,例如列表数据改为:
// 修改前 private MutableLiveData<List<Item>> itemList = new MutableLiveData<>(); // 修改后 private MutableLiveData<Event<List<Item>>> itemList = new MutableLiveData<>();
最后在HomeFragment的观察者逻辑中只消费未处理的事件:
postViewModel.getItemList().observe(getViewLifecycleOwner(), listEvent -> { List<Item> itemList = listEvent.getContentIfNotHandled(); if (itemList != null) { // 处理列表数据,刷新适配器 } });
3. 修正MainActivity的Binding作用域
将ViewBinding从局部变量改为成员变量,保证AppBarConfiguration持有有效的DrawerLayout引用:
@AndroidEntryPoint public class MainActivity extends AppCompatActivity { private AppBarConfiguration mAppBarConfiguration; public static Utils.DataStoreRepository DATA_STORE_REPOSITORY; // 新增成员变量存储binding private ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 赋值给成员变量,不要定义为局部变量 binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); // 原有逻辑保持不变 DATA_STORE_REPOSITORY = new Utils.DataStoreRepository(this); setSupportActionBar(binding.appBarMain.toolbar); mAppBarConfiguration = new AppBarConfiguration.Builder(R.id.nav_home, R.id.nav_Accessory, R.id.nav_Arcade, R.id.nav_Fashion, R.id.nav_Food, R.id.nav_Heath, R.id.nav_Lifestyle, R.id.nav_Sports, R.id.about) .setOpenableLayout(binding.drawerLayout) .build(); NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment); assert navHostFragment != null; NavController navController = navHostFragment.getNavController(); NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration); NavigationUI.setupWithNavController(binding.navView, navController); } @Override public boolean onSupportNavigateUp() { NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment); return NavigationUI.navigateUp(navController, mAppBarConfiguration) || super.onSupportNavigateUp(); } }
内容的提问来源于stack exchange,提问作者Dr Mido
相关产品推荐
相关产品推荐

