Search code examples
androidandroid-roomandroid-architecture-components

Comparing current values with last values in architecture component


I am getting a complex json from an api and I am saving the values with Architect component(Room).

Question:

  • Can I compare current values with last values that I saved in SQlite and if in compare I find a difference, update the RecyclerView?
  • Is this method logical?
  • Do you have a better way to offer?
  • If you have a better way to offer get me a sample(url sample)

Solution

  • Yes, you can do that and it is actually the recommended way. In order to do so, I think you should leverage the use of two other Architecture Components that were introduced with Android Jetpack, not only Room database: ViewModel and LiveData, but it is not mandatory.

    The important thing is to add an extra layer to your app called Repository:

    Repository modules handle data operations. They provide a clean API so that the rest of the app can retrieve this data easily. They know where to get the data from and what API calls to make when data is updated. You can consider repositories to be mediators between different data sources, such as persistent models, web services, and caches.

    So basically, the suggested architecture to handle this will look something like this:

    Android recommended architecture

    With that in mind, an example of a Repository that retrieves User data from a web service and save it to a local Room Database will look something like this:

    public class UserRepository {
        private final Webservice webservice;
        private final UserDao userDao;
        private final Executor executor;
    
        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());
                }
            });
        }
    }
    

    Then, your ViewModel will get the User Live Data doing something like this:

    ...
    user = userRepo.getUser(userId);
    ...
    

    And it will provide that LiveData to the UI layer with a public method:

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

    Finally, from your UI layer (an Activity or Fragment) you can observe the LiveData in the ViewModel and adapt the UI accordingly.

    viewModel.getUser().observe(this, user -> {
          // Update UI.
    });
    

    For a more complete explanation I suggest that you take a look to:

    1. Guide to app architecture in Android`s Developers website.
    2. This Github project with a basic example.
    3. This other Github project with a more complex example.