gpt4 book ai didi

java - 使用导航组件多次触发 LiveData 观察者

转载 作者:行者123 更新时间:2023-12-04 23:38:26 28 4
gpt4 key购买 nike

场景:我有两个名为 FirstFragment 的 fragment 和 UnitFragment .我来自 FirstFragmentUnitFragment选择一个单位返回FirstFragmet使用 navController.popBackStack();并将单位数据发送至FirstFragment这是观察单位数据。
这是我的onViewCreatedFirstFragment :

@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再次编码。
  • 避免再次触发 LiveData 观察者。
  • 最佳答案

    不幸的是,这不是您问题的答案:

    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/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com