Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I refresh viewModel livedata from another activity

Tags:

java

android

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?

like image 714
Benfactor Avatar asked Oct 18 '25 06:10

Benfactor


1 Answers

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);
}
  • When you want to update the data manually (from another activity), use menuRepository.update() method. This will post the data to your LiveData which will update all its observers, ie. the ViewModel.
  • Call menuRepository.loadMenu() when you want to get the data using API.
  • Use 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.

like image 190
Froyo Avatar answered Oct 20 '25 19:10

Froyo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!