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

LiveData,注册观察者时如何避免第一次回调

欧阳嘉年
2023-03-14

我想在片段中加载任务,在片段的onviewCreate中,我注册LiveDataobserver,在片段的onResume中,我异步加载任务,当第一次输入片段时,它工作正常,但当我导航到其他片段,然后返回到任务片段时,回调onChanged()将被调用两次。

我知道如果LiveData已经有了数据集,它将被传递给观察者,因此当返回到任务片段时,在onViewCreated中注册观察者时,将触发onChanged,在onResume中,将第二次触发onChanged,我想知道如何避免这种情况。我搜索了很多,我知道有一个EventWrapper,它可以标记第一次触发onchange时使用的内容。但我认为这种方法太重了。对不起,我的英语很差。。。

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle 
   savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    //...
    mainViewModel = ViewModelProviders.of(getActivity()).get(MainViewModel.class);
    mainViewModel.increaseTaskList.observe(getViewLifecycleOwner(), new 
    Observer<List<Task>>() {
        @Override
        public void onChanged(@Nullable List<Task> tasks) {
            Log.d("ZZZ","data changed,IncreaseTaskListAdapter setData");
            adapter.setData(tasks);
        }
    });
}

@Override
public void onResume() {
    super.onResume();
    mainViewModel.loadIncreasePointTaskList();
}

共有3个答案

巫马自明
2023-03-14

我的简单解决方案是,将一个布尔变量声明为isfisrcalled=false,然后第一次在回调中更改它true

isFirstCalled = false;

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle 
   savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    //...
    mainViewModel = ViewModelProviders.of(getActivity()).get(MainViewModel.class);
    mainViewModel.increaseTaskList.observe(getViewLifecycleOwner(), new 
    Observer<List<Task>>() {
        @Override
        public void onChanged(@Nullable List<Task> tasks) {
            if (!isFirstCalled) {
              isFirstCalled = true;
               return;
             } // this will ensure, you will discard fisrt callback
            Log.d("ZZZ","data changed,IncreaseTaskListAdapter setData");
            adapter.setData(tasks);
        }
    });
}

@Override
public void onResume() {
    super.onResume();
    mainViewModel.loadIncreasePointTaskList();
}
商夜洛
2023-03-14

我找到了一个简单的解决方案,在加载前检查livedata值

@Override
public void onResume() {
    super.onResume();
    if (mainViewModel.increaseTaskList.getValue()==null) {
        Log.d("ZZZ","IncreaseFragment loadTaskAsync");
        mainViewModel.loadIncreasePointTaskList();
    }
}
齐朝明
2023-03-14

您可以使用SingleLiveCase,只要内容没有更改,它就不会被触发。

不过,这是谷歌推荐的。

 类似资料:
  • 如何在收到第一个结果后移除观察者?下面是我尝试过的两种代码方式,但它们都不断接收更新,即使我已经删除了观察者。

  • 此外,为什么Viewmodel不能观察到它自己的LiveData的变化?

  • 我有一个视图模型,从场景中接收流作为livedata 在活动中,我们订阅了这个livedata,一些逻辑发生并使用了activityResult 当我们返回时,我们会用最后一个状态触发一个观察者,并再次执行之前的导航逻辑 如何忽略返回时具有相同值的观察者触发器?

  • 问题内容: 我有以下代码要使用。 尽管这似乎可行,但以下部分是什么意思? 这必须导致对象符合符合以下条件的Observer接口: 如何 结果对象与onChanged方法? 我不知道将接口名称放在lambda表达式前面意味着什么。 谢谢! 问题答案: 这称为SAM转换,该概念有助于与示例中的Java 单一抽象方法接口进行交互。 以下代码创建的实现,其中单个抽象方法是: 另外,但更冗长的是使用obje

  • 在livedata的observe方法中有这样一条评论 在给定所有者的生命周期内将给定的观察者添加到观察者列表中。事件在主线程上分派。如果LiveData已经有数据集,它将传递给观察者。 当我尝试向现有livedata实例添加新的观察者时,如果livedata具有数据集,则new观察者的onChanged方法调用。 有什么办法可以避免这种行为吗?我只是不想被通知新的观察员 SingleLiveEv