场景:我有两个名为 FirstFragment
的 fragment 和 UnitFragment
.我来自 FirstFragment
至UnitFragment
选择一个单位返回FirstFragmet
使用 navController.popBackStack();
并将单位数据发送至FirstFragment
这是观察单位数据。
这是我的onViewCreated
的 FirstFragment
:
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (viewModel == null) { // Lazy Initialization
ApiService apiService = ApiServiceProvider.getInstance();
AddNewWareViewModelFactory addNewWareViewModelFactory = new AddNewWareViewModelFactory(apiService);
viewModel = new ViewModelProvider(this, addNewWareViewModelFactory).get(AddWareViewModel.class);
}
Log.i(TAG, "OnViewCreated -----> Called");
viewModel.callNewWare(parentCode);
viewModel.getNewWareResponse().observe(getViewLifecycleOwner(),
resObject -> Log.i(TAG, "API Response LiveData Count -----> " + count++)); // Started From Zero
NavHostFragment navHostFragment = (NavHostFragment) requireActivity()
.getSupportFragmentManager()
.findFragmentById(R.id.container);
binding.button.setOnClickListener(v -> {
if (navHostFragment != null) {
NavController navController = navHostFragment.getNavController();
navController.navigate(FirstFragmentDirections.actionFirstFragmentToUnitFragment());
}
});
if (navHostFragment != null) {
NavController navController = navHostFragment.getNavController();
NavBackStackEntry navBackStackEntry = navController.getCurrentBackStackEntry();
if (navBackStackEntry != null) {
SavedStateHandle savedStateHandle = navBackStackEntry.getSavedStateHandle();
MutableLiveData<Unit> unitLiveData = savedStateHandle.getLiveData("unit_data");
unitLiveData.observe(getViewLifecycleOwner(), unit -> binding.tvUnit.setText(unit.getTitle()));
}
}
}
这是 LogCat 结果:--- Go to FirstFragment for first time ---
I/FirstFragment: OnViewCreated -----> Called
I/FirstFragment: API Response LiveData Count -----> 0
--- Button clicked to go to UnitFragment to select a unit ---
I/UnitFragment: Selected Unit -----> Meter
--- Come back to FirstFragment ---
I/FirstFragment: OnViewCreated -----> Called
I/FirstFragment: API Response LiveData Count -----> 1
I/FirstFragment: API Response LiveData Count -----> 2
正如您在 LogCat 结果中看到的,每次我单击按钮并转到 UnitFragment
并返回 FirstFragment
onViewCreated
将再次调用,API LiveDataObserver 将被触发两次!!!我知道 onViewCreated 会再次调用,因为导航组件替换了 fragment 而不是添加它们。但我不知道为什么 LiveData 观察者会被触发两次。
我读了this post但他似乎忽略了导航组件。
我需要一个解决方案...
onViewCreated
再次编码。 最佳答案
不幸的是,这不是您问题的答案:
I need a solution to ...
Avoid calling onViewCreated codes again.
Avoid triggering LiveData observer again.
我试图解释导航及其行为或纠正一些误解。这些问题有不同的原因和
Avoid calling onViewCreated codes again.
是一种迂回的方式。I know onViewCreated will call again because Navigation Component replaces the fragments instead of adding them.
如您所知,将 fragment 添加到后台堆栈时进行替换,只需将旧 fragment 从
fragmentManager
中分离出来.表示旧 fragment 的查看 会破坏。当您从后台堆栈中弹出 UnitFragment 时,将创建其 View 。
所以不要在
onViewCreated
中调用任何 API。因为它可能会调用多次(在配置更改、破坏 fragment 等中)最好使用
onCreate
用于初始化非 View 相关的组件(ViewModel + API 调用)。它减少了 Lazy(!?) Initialization
查看。@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ApiService apiService = ApiServiceProvider.getInstance();
AddNewWareViewModelFactory addNewWareViewModelFactory = new AddNewWareViewModelFactory(apiService);
viewModel = new ViewModelProvider(this /*owner*/, addNewWareViewModelFactory).get(AddWareViewModel.class);
viewModel.callNewWare(parentCode);
}
并开始在 onViewCreated
中观察它们.此外,您应该使用 unit_data
当你得到它时,来自 navBackStackEntry。if (navHostFragment != null) {
NavController navController = navHostFragment.getNavController();
NavBackStackEntry navBackStackEntry = navController.getCurrentBackStackEntry();
if (navBackStackEntry != null) {
SavedStateHandle savedStateHandle = navBackStackEntry.getSavedStateHandle();
MutableLiveData<Unit> unitLiveData = savedStateHandle.getLiveData("unit_data");
unitLiveData.observe(getViewLifecycleOwner(), unit -> {
savedStateHandle.remove("unit_data"); // add this line
return binding.tvUnit.setText(unit.getTitle());
});
}
}
关于java - 使用导航组件多次触发 LiveData 观察者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67581800/