Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android ViewModel LiveData update view on button click

I am following this tutorial to learn ViewModel and LiveData. In my case, instead of getting data from network, I am simply generating random string on button click and trying to update a textview. The problem is that the textview does not get updated when the data is changed by button click, but only gets updated when orientation is toggled.

Activity Class (extends LifecycleActivity)

public class PScreen extends BaseActivity {
  @Override protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.places_screen);

final UserModel viewModel = ViewModelProviders.of(this).get(UserModel.class);
viewModel.init();

viewModel.getUser().observe(this, new Observer<User>() {
  @Override public void onChanged(@Nullable User user) {
    ((TextView) findViewById(R.id.name)).setText(user.getName());
  }
});

findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
  @Override public void onClick(View v) {
    final MutableLiveData<User> data = new MutableLiveData<>();
    User user = new User();
    user.setName(String.valueOf(Math.random() * 1000));
    data.postValue(user);
    viewModel.setUser(data); // Why it does not call observe()
  }
});
  }
}

ViewModel Class

package timsina.prabin.tripoptimizer.model;

import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.ViewModel;

public class UserModel extends ViewModel {
  private LiveData<User> user;

  public void init() {
    if (this.getUser() != null) {
      return;
    }
    this.user = new LiveData<User>() {
      @Override protected void setValue(User value) {
        value.setName("Fresh New Name");
        super.setValue(value);
      }
    };
  }

  public LiveData<User> getUser() {
    return user;
  }

  public void setUser(LiveData<User> user) {
    this.user = user;
  }
}
like image 635
Prabin Timsina Avatar asked Aug 18 '26 05:08

Prabin Timsina


1 Answers

You are creating a new LiveData instance each time! You are not supposed to do that. If you do that all previous observers will be ignored.

In this case you could replace your setUSer(LiveData<User>) method on your ViewModel to setUser(User u) (taking a User instead of a LiveData) and then do user.setValue(u) inside it.

Of course, will have to initialize the LiveData member in your ViewModel class, like this:

final private LiveData<User> user = new MutableLiveData<>();

It will work then because it will notify the existing observers.

like image 156
niqueco Avatar answered Aug 21 '26 09:08

niqueco