0

i'd like to ask about the way MVP and dagger working. So, in android development, we know that Activity and fragment is a view, and we make presenter by implementing observer (in my case, im using rxjava + retrofit). And the dagger in this case I use to inject Rest service (Network Component -> retrofit).

I still confuse to inject Rest service to my presenter, because all the example I found is injecting to activity.

here is my code.

As view :

public class PageFragment extends Fragment implements ScheduleViewInterface{
private ScheduleCursorAdapter scheduleAdapter;
@Inject RestApi restApiInject;
private SchedulePresenter mPresenterJson;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    App.getApiComponent(getActivity()).inject(this);
    mPresenterJson.fetchSchedule();
}

@Override
public Observable<ScheduleList> getSchedule() {
    return restApiInject.getScheduleListByUrl("url here");
}

As presenter :

public class SchedulePresenter implements Observer<ScheduleList> {
private ScheduleViewInterface mInterface;

public SchedulePresenter(ScheduleViewInterface viewInterface){
    mInterface = viewInterface;
}

@Override
public void onCompleted() {
    mInterface.jsonCompleted();
}

@Override
public void onError(Throwable e) {
    mInterface.jsonError(e.getMessage());
}

@Override
public void onNext(ScheduleList scheduleList) {
    mInterface.jsonScheduleList(scheduleList);
}

public void fetchSchedules(){
    unSubscribeAll();
    subscribe(mInterface.getSchedule(), SchedulePresenter.this);
}

and this is my dagger2 code

@CustomScope
@Component(modules = ApiModule.class, dependencies = NetworkComponent.class)
public interface ApiComponent {
MainActivity inject(MainActivity activity);
PageFragment inject(PageFragment fragment);
}

Architecture pattern

Raffu
  • 27
  • 1
  • 9
  • Here's a sample. https://github.com/anupcowkur/MVPSample. – Raghunandan Oct 01 '16 at 05:11
  • I'm pretty sure that the answer on your question lies in the [answer by David Medenjak](http://stackoverflow.com/questions/35605408/dagger-2-injection-in-non-activity-java-class) – Teodor Hirs Oct 02 '16 at 10:16

2 Answers2

0

best practice is to create a Interactor class to handle this, and then inject that interactor in the presenter. look at my code in my project below to understand. the presenter code is :

public class PopularMoviesPresenterImpl implements PopularMoviesPresenter {

@Inject
public PopularMoviesInteractor interactor;

private PopularMoviesView view;
private Subscription subscription = Subscriptions.empty();

@Inject
public PopularMoviesPresenterImpl() {
}

@Override
public void setView(PopularMoviesView view) {
    this.view = view;
}

@Override
public void destroy() {
    if (subscription != null && !subscription.isUnsubscribed())
        subscription.unsubscribe();

    interactor.onDestroy();

    view = null;
    interactor = null;
}

@Override
public void loadPopularMoviesData(boolean isConnected, int page, int limit) {

    if (null != view) {
        view.showProgress();
    }

    subscription = interactor.loadPopularMovies(page, limit).subscribe(movies ->
            {
                if (null != view) {
                    view.hideProgress();
                    view.setPopularMoviesValue(movies);

                    if (!isConnected)
                        view.showOfflineMessage();
                }
            },
            throwable -> {
                if (null != view) {
                    view.hideProgress();
                }

                if (isConnected) {
                    if (null != view) {
                        view.showRetryMessage();
                    }
                } else {
                    if (null != view) {
                        view.showOfflineMessage();
                    }
                }
            });

}}

the interactor is:

public class PopularMoviesInteractorImpl implements PopularMoviesInteractor {
private TraktApi api;
private SchedulerProvider scheduler;

private ReplaySubject<Movie[]> moviesDataSubject;
private Subscription moviesSubscription;

@Inject
public PopularMoviesInteractorImpl(TraktApi api, SchedulerProvider scheduler) {
    this.api = api;
    this.scheduler = scheduler;
}

@Override
public Observable<Movie[]> loadPopularMovies(int page, int limit) {
    if (moviesSubscription == null || moviesSubscription.isUnsubscribed()) {
        moviesDataSubject = ReplaySubject.create();

        moviesSubscription = api.getPopularMovies(page, limit, Constants.API_EXTENDED_FULL_IMAGES)
                .subscribeOn(scheduler.backgroundThread())
                .observeOn(scheduler.mainThread())
                .subscribe(moviesDataSubject);
    }

    return moviesDataSubject.asObservable();
}

@Override
public void onDestroy() {
    if (moviesSubscription != null && !moviesSubscription.isUnsubscribed())
        moviesSubscription.unsubscribe();
}}

the interactor interface:

public interface PopularMoviesInteractor {

Observable<Movie[]> loadPopularMovies(int page, int limit);

void onDestroy();}

and in your module write:

 @Provides
public PopularMoviesInteractor provideInteractor(PopularMoviesInteractorImpl interactor) {
    return interactor;}

the interactor is provided through construction injection.(you can do it with simple injection though)

here is a clean example of the mvp: http://github.com/mmirhoseini/fyber_mobile_offers

Mohsen Mirhoseini
  • 8,454
  • 5
  • 34
  • 59
Amir Ziarati
  • 14,248
  • 11
  • 47
  • 52
  • I cant open the link you provided, please if you mind to give me the access (aunorafiq). soon ill mark this as an answer, thank you – Raffu Oct 01 '16 at 11:24
0

I see that this question was already answered. But if you want a clear example on how to use dependency injection in MVP architecture I would really suggest you to check this boilerplate since it is fully based on DI using Dagger2 and it's following MVP architecture.

The dependencies currently handled by the boiler plate are the following:

  • Database dependency: encapsulates all the database operations.
  • Shared preferences dependency: deals with shared preferences.
  • Local files dependency: which deals with saving on files.
  • Analytics dependency: covers all the operation of reporting events to your analytics backend (GA, Segment, FB, Flurry ..)
  • Logging dependency: encapsulates all the operations related to logging to your console
  • Api dependency: encapsulates all the API related operations

The power of dependency injection comes really handy especially for testing since you can easily switch your dependencies in the test environment to dummy dependencies.

Abed Almoradi
  • 131
  • 1
  • 2