Android ViewModel LiveData update view on button click

自作多情 提交于 2020-01-13 19:21:34

问题


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

回答1:


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.




回答2:


I was somehow able to resolve this by using MutableLiveData instead of LiveData. Model class

private MutableLiveData<User> user2;
  public void init() {
    if (user2 == null) {
      user2 = new MutableLiveData<>();
    }
}

  public MutableLiveData<User> getUser2() {
    return user2;
  }

  public void setUser2(final User user) {
    user2.postValue(user);
  }

Activity

 viewModel.getUser2().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) {
       User user = new User();
        viewModel.getUser().postValue(user);
        }
    });



回答3:


You replace the reference to the object inside UserModel, try to swap the lines of code

data.postValue(user);
viewModel.setUser(data); // Why it does not call observe()

replace on

viewModel.setUser(data); // Why it does not call observe()
data.postValue(user);



回答4:


Try to modify your code as @niqueco mentioned, set your updated method inside setUser() method and change your onclick() listener in the activity to send the new user data info only. Other works the LiveData will help u.

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.setValue(user); //the live data will help u push data
  }
}

Activity Class

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(user); // Why it does not call observe() 
  }
});
  }
}


来源:https://stackoverflow.com/questions/44150912/android-viewmodel-livedata-update-view-on-button-click

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!