Reputation: 599
I am developing android application and I want to refresh viewModel livedata from second activity. When I get back to first activity data is not refreshed.
FirstActivity:
mViewModel = ViewModelProviders.of(this).get(MenuViewModel.class);
mViewModel.getMenus().observe(this, menuResponse -> {
if (menuResponse != null) {
resMenus.addAll(menuResponse.getMenus());
progressBar.setVisibility(View.GONE);
mAdapter.notifyDataSetChanged();
}
});
MenuViewModel:
public class MenuViewModel extends AndroidViewModel {
private MutableLiveData<MenuResponse> restMenuData;
private MenusRepository mRepository;
public MainActivityViewModel(@NonNull Application application) {
super(application);
mRepository = MenusRepository.getInstance(application);
restMenuData = mRepository.getMenus();
}
public LiveData<MenuResponse> getMenus() {
return restMenuData;
}
}
MenusRepository
private MenusRepository(Context context) {
apiRequest= RetrofitInstance.getInstance(context).getApiRequest();
}
public synchronized static MenusRepository getInstance(Context context) {
if (projectRepository == null) {
projectRepository = new MenusRepository(context);
}
return projectRepository;
}
public MutableLiveData<MenuResponse> getMenus() {
final MutableLiveData<MenuResponse> data = new MutableLiveData<>();
apiRequest.getMenus().enqueue(new Callback<MenuResponse>() {
@Override
public void onResponse(@NonNull Call<MenuResponse> call, @NonNull Response<MenuResponse> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(response.body());
}
}
@Override
public void onFailure(@NonNull Call<MenuResponse> call, @NonNull Throwable t) {
data.setValue(null);
}
});
return data;
}
SecondActivity:
MenuViewModel mViewModel = ViewModelProviders.of(Objects.requireNonNull(SecondActivity.this)).get(MenuViewModel.class);
mViewModel.getMenus();
// This line not refresh menus
I except to refresh data from viewmodel, but it return old data. How can I refresh viewmodel data in best practices?
Upvotes: 4
Views: 5584
Reputation: 18477
MenusRepository.getMenus()
methods creates a new instance of LiveData
for every call. This is not the correct way to go about it.
You should have only one instance of LiveData
and different objects subscribe to it (activity, viewModel, etc).
What you could do is - create a singleton of MenusRepository
(which I think you have already done). Create one instance of MutableLiveData
only and use it to update the data.
class MenusRepository {
private val liveData = MutableLiveData<MenuResponse>()
fun getMenus() {
// Your api call. Do not create a new instance of the livedata.
}
fun menus(): LiveData<MenuResponse> {
return liveData
}
fun update(data: MenuResponse) {
liveData.post(data)
}
This code is in Kotlin, but it applies similarly to Java as well.
You can update
method to post an update to liveData. When you update it, all the observers will receive the new data. Use MenusRepository.menus()
to access LiveData in your ViewModel.
Update
Your MenuRepository
class could be like this.
private final MutableLiveData<MenuResponse> liveData = new MutableData<>();
private MenusRepository(Context context) {
apiRequest= RetrofitInstance.getInstance(context).getApiRequest();
}
public synchronized static MenusRepository getInstance(Context context) {
if (projectRepository == null) {
projectRepository = new MenusRepository(context);
}
return projectRepository;
}
public MutableLiveData<MenuResponse> loadMenus() {
apiRequest.getMenus().enqueue(new Callback<MenuResponse>() {
@Override
public void onResponse(@NonNull Call<MenuResponse> call, @NonNull Response<MenuResponse> response) {
if (response.isSuccessful() && response.body() != null) {
liveData.setValue(response.body());
}
}
@Override
public void onFailure(@NonNull Call<MenuResponse> call, @NonNull Throwable t) {
liveData.setValue(null);
}
});
}
public LiveData<MenuResponse> getMenus() {
return liveData;
}
public void updateData(response: MenuResponse) {
liveData.postValue(response);
}
menuRepository.update()
method. This will post the data to your LiveData which will update all its observers, ie. the ViewModel.menuRepository.loadMenu()
when you want to get the data using API.menuRepository.getMenus()
to get the LiveData and attach your observers.Since MenuRepository
is a singleton, there's only one instance of LiveData
. When you will post an update to this instance of LiveData, all the observers will receive the new data.
Upvotes: 3
Reputation: 1274
public class MenuViewModel extends AndroidViewModel {
private MutableLiveData<MenuResponse> restMenuData;
private MenusRepository mRepository;
public MainActivityViewModel(@NonNull Application application) {
super(application);
mRepository = MenusRepository.getInstance(application);
restMenuData = mRepository.getMenus();
}
public LiveData<MenuResponse> getMenus() {
restMenuData = new MutableLiveData<>();
return restMenuData;
}
}
Change the View model code as above. So that the live data is always cleared before returning to activity.
Upvotes: 0