Search code examples
javaandroid-roomandroid-architecture-componentsandroid-livedataandroid-mvvm

how to communicate to activity/fragment from repository class for web service in MVVM architecture


I am new to MVVM architecture and i just want to know how to communicate between repository class and the UI (activity/fragment) class.I came across with live data which is doing this job for updating same entities from both (remote and room database).

For example : 1) If i have entity named User. I can save and the observe it using live data like below : (from android developers website).

    public class UserRepository {
    private final Webservice webservice;
    private final UserDao userDao;
    private final Executor executor;

    @Inject
    public UserRepository(Webservice webservice, UserDao userDao, Executor executor) {
        this.webservice = webservice;
        this.userDao = userDao;
        this.executor = executor;
    }

    public LiveData<User> getUser(String userId) {
        refreshUser(userId);
        // Returns a LiveData object directly from the database.
        return userDao.load(userId);
    }

    private void refreshUser(final String userId) {
        // Runs in a background thread.
        executor.execute(() -> {
            // Check if user data was fetched recently.
            boolean userExists = userDao.hasUser(FRESH_TIMEOUT);
            if (!userExists) {
                // Refreshes the data.
                Response<User> response = webservice.getUser(userId).execute();

                // Check for errors here.

                // Updates the database. The LiveData object automatically
                // refreshes, so we don't need to do anything else here.
                userDao.save(response.body());
            }
        });
    }
}

2) But how can we do this in other API'S like (login) which does not need live data but i just want to show or hide progress dialog depend on the network success or error messages.

public void isVerifiedUser(int userId){
      executor.execute(() -> {
        // making request to server for verifying user

        Response<User> response = webservice.getVerifyUser(userId).execute();

          // how to update the UI like for success or error.
          //update the progress dialog also in UI class
        });
}

Solution

  • You need to make isVerifiedUser() return a liveData which you can observe inside the viewModel related to that UI(activity/fragment).

    1. Inside Repository:

    public LiveData<State> isVerifiedUser(int userId){
    
        MutableLiveData<State> isVerified = new MutableLiveData();
    
        executor.execute(() -> {           
            Response<User> response = webservice.getVerifyUser(userId).execute();
            // Update state here.
            isVerified.postValue(valueHere)
        });
    
        return isVerified;
    }
    

    2. ViewModel:

     public ViewModel(final Repository repository) {
            //observe userId and trigger isVerifiedUser when userId value is changed
            stateLiveData = Transformations.map(userId, new Function<>() {
                @Override
                public RepoMoviesResult apply(Integer userId) {
                    return repository.isVerifiedUser(userId);
                }
            });
        }
    

    3. Activity:

    viewModel.getStateLiveData ().observe(this, new Observer<>() {
        @Override
        public void onChanged(State state) {
             //do something here
        }
    });
    

    More Infos:

    LiveData

    ViewModel

    Guide to app architecture MVVM