androidrepositorymvppresenter

How can I use Repository


I use Dagger2 and Moxy with MVP. As I understand, Presenter can call the Repository for loading and unloading data from the database. But I just can not figure out how to create an instance of the repository: in the Activity with the help of Dagger and transfer to the presenter or in the presenter itself?

I used Repository in Activity but I think it's an anti-pattern.

It provides Context

 @Module
 public class AppModule {
   private Context context;

   public AppModule(Context context){
       this.context = context;
   }

   @Singleton
   @Provides
   Context provideContext(){
       return context;
   }
 }

This module provides Room

 @Module
 public class RoomModule {
   @Singleton
   @Provides
   AppDataBase providesAppDataBase(Context context) {
     return Room.databaseBuilder(context, AppDataBase.class, "budget")
             .fallbackToDestructiveMigration()
             .allowMainThreadQueries()
             .build();
   }

@Singleton
@Provides
BudgetDao providesDao(AppDataBase database) {
    return database.getBudgetDao();
 }

 @Singleton
 @Provides
 DetailDao providesDetailDao(AppDataBase dataBase){
     return dataBase.getDetailDao();
 }
  }

AppComponent

@Singleton
@Component(modules = {RoomModule.class, AppModule.class})
public interface AppComponent {

void inject(BudgetListPresenter presenter);

void inject(BudgetsActivity activity);

void inject(DetailActivity activity);
 }

Repository.class

 @Singleton
 public class BudgetListRepository implements BudgetRepository {
 private BudgetDao budgetDao;

 @Inject
 public BudgetListRepository(BudgetDao budgetDao){
     this.budgetDao = budgetDao;
 }

 @Override
 public void updateBudget(Budget budget) {
     budgetDao.updateBudget(budget);
 }

 @Override
 public void addBudget(Budget budget) {
     budgetDao.insertBudget(budget);
 }

 @Override
 public void deleteBudget(Budget budget) {
     budgetDao.deleteBudget(budget);
 }

 @Override
 public Budget getBudget(String id) {
     return budgetDao.getBudget(id);
 }

 @Override
 public List<Budget> getAll() {
     return budgetDao.getAll();
 }
}

Solution

  • The flow should be like this

    First, you call a method from your view to your presenter.

    Then, in your presenter, you need to communicate with any use case in your domain layer and that layer has the responsibility to inject the repository with dagger.

    Let me show you an example

    From your presenter, you inject your use case (interactor), this will be the responsable to communicate with the repository later

    class LoginPresenter @Inject constructor(private val signInInteractor: SignInInteractor) : LoginContract.Presenter {
    ...
    
    override fun signInWithEmailAndPassword(email: String, password: String) {
    signInInteractor.signInWithEmailAndPassword(email, password)
    ...
    

    Then your interactor should inject the repository like this

    class SignInInteractorImpl @Inject constructor(val userRepository: UserRepository): SignInInteractor{
    ...
    
     override suspend fun pushUserIntoDatabase(account: GoogleSignInAccount): Unit = suspendCancellableCoroutine { continuation ->
            userRepository.createUser(account.displayName!!,account.email!!,object : UserRepository.UserRepositoryCallback{
    
                override fun onRemoteSuccess() {
                    //success
                }
    
                override fun onRemoteFailure(errormsg:String) {
                    //failure
                }
    
            })
    
        }
    

    In this case I just use inside my use case a call to the repository to push data into Firebase

    And in my PresentationModule I just inject that repo

     @Provides
        @Singleton
        fun provideUserRepositoryToLogin(userRepository: UserRepository): SignInInteractor {
            return SignInInteractorImpl(userRepository)
        }
    

    This is the concept to follow

    enter image description here