Alin
Alin

Reputation: 14571

Applying MVVM between ViewModel and Fragment/Activity interactions and communication

I am investing a lot of time into properly understanding of architecture components and the how everything fits into MVVM pattern. So far here's how I see things (without doing Dagger injection as I haven't got that far yet):

a) UserEntity is a class with @Entity annotation to handle Room's table creation

@Entity(tableName="users")
public class Users{
   private long id;
   private String name;
}

b) User pojo class in the model to use it around the app and has supplemental fields as needed.

public class User{
   private long id;
   private String name;
   private List<Role> roles;
   private Preferences preferences;
}

beside this there can be different pojos depending on what I need from db, for instance, UserWithRoles

c) UserDao takes care of getting or inserting/updating info in the room database. In here, for @Insert, @Update I can user the UserEntity but for @Query I can also use the pojo classes

@Dao 
public abstract class UserDao{
    @Insert
    public abstract long insertUser(User user)

   @Query("Select someFields from inner joined tables")
   public abstract LiveData<List<UserRoles> getUsersWithRoles();
}

d) Have RepositoryUser as the repository between ViewModel and Dao

public class RepositoryUser{
       private UserDao userDao;

      public RepositoryUser(Application app){
            Database db = Databaase.getDatabase(app.getApplicationContext);
            userDao = db.userDao(); 
      }
      public LiveData<List<UserWithRoles>> getUsersWithRoles(){
            return userDao.getUsersWithRoles()
      }
    }

e) UserWithRolesViewModel to be available for the fragment that shows the list with users and their roles

public class UserWithRolesViewModel extends AndroidViewModel{
  private RepositoryUser repositoryUser;

  public UserWithRolesViewModel(Application app){
         super(app);
         repositoryUser = new RepositoryUser(app);
  }

  public LiveData<List<UserWithRoles>> getUsersWithRoles(){
                return repositoryUser.getUsersWithRoles()
          }
}

f) In my fragment I can do something like:

public void onCreate(...){
    viewModel = ViewModelProviders.of(this).get(UserWithRolesViewModel.class);
}

public View onCreateView(...){
  viewModel.getUsersWithRoles().observe(...)
          public void onChanged(...){
          adapter.setData(...);
       }
}

However, there are some pieces that are missing. From my understanding according to MVVM the view should only be responsible for showing info, so no actual logic or even handling to be made inside the fragment or activity. At this point I have 2 questions:

  1. On the regular way, I would create an interface, for instance onFragmentAction and implement it in activity. Then on fragment when I wanted to inform the activity to do something, I would do callback.onFragmentAction(params) and the onFragmentAction in the activity would fire and act accordingly. How is this scenario handled in MVVM? How does a fragment talk to it's parent activity?
  2. On the regular way I would have inside the fragment's onCreateView, inflate the layout, use findViewById to get the views and use, for instance textView.setText() or button.setOnClickListener(). How can this be done in MVVM? Use DataBinding?

Upvotes: 3

Views: 5576

Answers (1)

Ioane Sharvadze
Ioane Sharvadze

Reputation: 2148

On the regular way, I would create an interface, for instance onFragmentAction and implement it in activity. Then on fragment when I wanted to inform the activity to do something, I would do callback.onFragmentAction(params) and the onFragmentAction in the activity would fire and act accordingly. How is this scenario handled in MVVM? How does a fragment talk to it's parent activity?

For interaction, you can create ViewModel that is shared between Fragment and Activity. In that case you have an abstraction, where you push some data in ViewModel LiveData where it gets an event whoever listens to same ViewModel.

For example this method is recommended for Fragment to Fragment communications, but I think it also fits Fragment to Activity.

On the regular way I would have inside the fragment's onCreateView, inflate the layout, use findViewById to get the views and use, for instance textView.setText() or button.setOnClickListener(). How can this be done in MVVM? Use DataBinding?

You can use either DataBinding or Kotlin Android Extension, both should be fine with MVVM. Through DataBinding should be better, since it will reduce boilerplate. But personally I find Kotlin Android Extensions also very clean.

Upvotes: 4

Related Questions