Saturday, 22 May 2021

LiveData observer is being triggered multiple times using Navigation Component

Scenario: I have two fragments named FirstFragment and UnitFragment. I go from FirstFragment to UnitFragment to select a unit to come back to FirstFragmet using navController.popBackStack(); and send unit data to FirstFragment which is observing unit data.

This is my onViewCreated of 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()));
        }
    }
}

This is the LogCat result:

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

As you see in LogCat result, every time I click the button and go to UnitFragment and come back to FirstFragment the onViewCreated will call again and API LiveDataObserver will be triggered TWO times!!!

I know onViewCreated will call again because Navigation Component replaces the fragments instead of adding them. but I don't know why LiveData observer is being triggered two times.

I read this post but he seems to have ignored Navigation Component.

I need a solution to ...

  1. Avoid calling onViewCreated codes again.
  2. Avoid triggering LiveData observer again.


from LiveData observer is being triggered multiple times using Navigation Component

No comments:

Post a Comment