LiveData, как избежать первого обратного вызова при регистрации наблюдателя - PullRequest
1 голос
/ 19 июня 2019

Я хочу загрузить задачи во фрагменте, в onViewCreated фрагмента, я регистрирую наблюдатель LiveData, во фрагменте onResume, я загружаю задачу асинхронно, при первом вводе фрагмента она работает нормально, но когда я перехожу к другимзатем фрагменты возвращаются к фрагменту задачи, обратный вызов onChanged() будет вызван дважды.

Я знаю, если LiveData уже имеет набор данных, он будет доставлен наблюдателю, поэтому, когда он вернется к фрагменту задачи, onChanged сработает при регистрации наблюдателя в onViewCreated, а в onResume сработает onChanged во второй раз, я хочу знать, как этого избежать.Я много искал, знаю, что есть EventWrapper, который может помечать контент, использованный при первом запуске onChanged.но я думаю, что этот подход слишком тяжелый.Извините за мой плохой английский ...

@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 ]

1 голос
/ 19 июня 2019

Я нашел простое решение, проверьте значение liveata перед загрузкой

@Override
public void onResume() {
    super.onResume();
    if (mainViewModel.increaseTaskList.getValue()==null) {
        Log.d("ZZZ","IncreaseFragment loadTaskAsync");
        mainViewModel.loadIncreasePointTaskList();
    }
}
0 голосов
/ 19 июня 2019

Мое простое решение состоит в том, чтобы объявить одну логическую переменную как isFisrtCalled = 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();
}
0 голосов
/ 19 июня 2019

Вы можете использовать SingleLiveEvent, который не будет срабатывать, пока содержимое не изменилось.

Однако это рекомендуется Google.

...