当前位置: 首页 > 知识库问答 >
问题:

使用导航组件多次触发LiveData observer

公冶泰
2023-03-14

场景:我有两个片段,分别名为FirstFragmentUnitFragment。我从firstfragment转到unitfragment选择一个单元,使用navcontroller.popbackstack()返回到firstfragmet,并将单元数据发送到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将再次调用,因为导航组件替换了片段,而不是添加它们。但我不知道为什么LiveData observer被触发了两次。

    null

共有1个答案

司徒英卓
2023-03-14

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

我需要解决...

避免再次调用onViewCreated代码。

最好使用oncreate来初始化与视图无关的组件(ViewModel+API调用)。它减少了lazy(!?)初始化检查。

@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中观察它们。此外,当您获得navBackStackEntry时,应该使用它的unit_data

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());
        });
    }
}

 类似资料:
  • 我对TextWatcher有一个恼人的问题。我一直在网上搜索,但什么也找不到。如果有人能帮助我,我将不胜感激。 由于某些原因,在一次文本更改时对TextWatcher事件的调用是不稳定的。有时它们被触发一次(就像它们应该被触发的那样),有时两次,有时三次。不知道为什么,整个事情都很直截了当。有时,PostTextChanged()上的可编辑参数在toString()和length()中返回空值。

  • 导航组件说明 组件 说明 最低版本 navigator 页面链接 1.0.0 functional-page-navigator 用于跳转插件功能页 不支持 navigator 属性 类型 默认值 必填 说明 最低版本 url string 否 当前小程序内的跳转链接 open-type navigate 否 跳转方式 hover-class string navigator-hover 否 指定

  • 我正在一个新的Android应用程序上使用导航组件,但我不知道怎么做 首先,我有我的主活动,我有main_navigation_graph 主要活动 NavHostFragment main_navigation_graph里面有3个碎片 这里一切都很好。问题是当我到达最后一个片段时,因为在这个片段上,我想根据BottomNavigationView输入(暂时)显示一些子片段(在新的NavHost

  • 我有一个 Blob 存储容器,其中配置了事件网格触发器(Blob 已创建)。我正在通过数据工厂加载此 blob 存储文件,很多时候,许多文件可能会在一次尝试中出现在此 blob 中。也许我们可以举一个20个文件的例子。 好消息是我的事件网格触发器启动了,函数app被调用。然而,我发现有时对于同一个文件,事件网格触发器被触发了不止一次。 在这20个文件中,很少有文件非常大,比如300 MB,但其他文

  • 问题内容: 我试图用Javascript编写视频扑克游戏,以降低其基础知识,但是我遇到了一个问题,其中jQuery click事件处理程序多次触发。 它们被附加到用于下注的按钮上,并且对于在游戏过程中第一手下注(仅触发一次)非常有效。但是在秒针下注中,每次按下一个下注或下注按钮都会触发两次点击事件(因此,每次按下正确的赌注量是两次)。总体而言,在按一次下注按钮时,触发单击事件的次数遵循此模式序列的