Home > Software engineering >  Why LiveData observer is not called? (Android, Fragment)
Why LiveData observer is not called? (Android, Fragment)

Time:12-03

My Observer is not called even though the LiveData value changes. What am I doing wrong?

The observer and the model are initialized in a fragment. A button is used to change the value in the model via a method (calculation followed by a set method). However, the observer does not register any change of the model value.

Fragment

public class PlayerFragment extends Fragment {

    private PlayerViewModel mViewModel;
    private ImageButton volumeUp, volumeDown;

    public static PlayerFragment newInstance() {
        return new PlayerFragment();
    }

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
       
        volumeDown = getView().findViewById(R.id.btn_player_volume_down);
        volumeDown.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                mViewModel.volumeDown();
            }
        });

        volumeUp = getView().findViewById(R.id.btn_player_volume_up);
        volumeUp.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                mViewModel.volumeUp();
            }
        });

        final Observer<Integer> volumeObserver = new Observer<Integer>() {
            @Override
            public void onChanged(Integer volValue) {
                SeekBar volume = getView().findViewById(R.id.player_volumeBar);
                volume.setProgress( volValue );
            }
        };

        mViewModel.getVolume().observe(getViewLifecycleOwner(), volumeObserver);
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mViewModel = new ViewModelProvider(this).get(PlayerViewModel.class);
        return inflater.inflate(R.layout.fragment_player, container, false);
    }

    @Override
    public void onResume() {
        super.onResume();
        ((MainActivity) getActivity()).getSupportActionBar().setTitle( getString(R.string.fragment_player_title) );
        mViewModel.fetchPlayerData();
    }

}

ViewModel


public class PlayerViewModel extends ViewModel {

    private MutableLiveData<Integer> volume;

    public PlayerViewModel(){
        volume = new MutableLiveData<Integer>();
        fetchPlayerData();
    }

    public void fetchPlayerData(){
        volume = new MutableLiveData<Integer>(1);
    }
    public void volumeUp() {
        volume.postValue( volume.getValue()   5 );
        Log.i( "volumeUp", "Set new volume:"   volume.getValue().toString() );
    }

    public void volumeDown() {
        volume.postValue( volume.getValue() - 5 );
        Log.i( "volumeDown", "Set new volume:"   volume.getValue().toString() );
    }
}

CodePudding user response:

Method fetchPlayerData() assigns volume a new MutableLiveData, which causes the observer that was registered on the old one to be lost. It's called in onResume() again, after the observer was registered.

You could change fetchPlayerData() to something like this:

volume.postValue(1)
  • Related