Search code examples
androidandroid-architecture-componentsandroid-livedata

Should we use lambda or anonymous class to observe LiveData


I realize there is a significant different, when using lambda and anonymous class to observe LiveData

Anonymous class

button.setOnClickListener(e -> {
    mainViewModel.getCounter().observe(MainFragment.this, new Observer<Integer>() {
        @Override
        public void onChanged(@Nullable Integer counter) {
            android.util.Log.i("CHEOK", "Observer 3 : " + counter + ", " + this);
        }
    });
});

Lamda

button.setOnClickListener(e -> {
    mainViewModel.getCounter().observe(MainFragment.this, counter -> {
        android.util.Log.i("CHEOK", "Observer 3 : " + counter);
    });
});

When you click on the button multiple times, for anonymous class, multiple different instances of observes will be created, and passed to LiveData. Hence, if you press the button 3 times, and execute

counter.postValue(counter.getValue());

You will get

Observer 3 : 123, com.xxx.MainFragment$1@cd023a
Observer 3 : 123, com.xxx.MainFragment$1@beb52e1
Observer 3 : 123, com.xxx.MainFragment$1@d1ffcf4

But for lamda, even if you press the button multiple times, only a single instance of Observer will ever be created. You will only get

Observer 3 : 123

Android guideline doesn't specifically mentions such catch. I was wondering, should we be using Anonymous class, or Lambda to observe LiveData?


Solution

  • It would be better to not create new observers with each button click. Instead take that out of the click callback and place it into your Activity / Fragment initialization code. For example, into your onCreate method of your Activity.

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        mainViewModel.getCounter().observe(MainFragment.this, new Observer<Integer>() {
            @Override
            public void onChanged(@Nullable Integer counter) {
                android.util.Log.i("CHEOK", "Observer 3 : " + counter + ", " + this);
            }
        });
    }
    

    Then to increment your counter, you need to tell your ViewModel that the data should change. In your case mainViewModel.incrementCounter();. If you also use the Repository design pattern, then you should call mainRepository.incrementCounter(); within your ViewModel.

    At this point, you can then access your MutableLiveData<Integer> instance, and increment it. It is typically a good idea to use the postValue(...) method, as that will send the updates over the main thread. Which is important for UI updates.

    (and to answer your end-question: it really shouldn't matter whether your use anonymous or lambdas, though lambdas are simply prettier - making the changes I mention above should clear up your main issues though)