Dagger2:向演示者注入 Api 模块(MVP)
Dagger2: inject Api Module to presenter (MVP)
我想问一下MVP和dagger的工作方式。所以,在 android 开发中,我们知道 Activity 和 fragment 是一个视图,我们通过实现观察者来制作演示者(在我的例子中,我使用 rxjava + retrofit)。在这种情况下,我使用匕首来注入 Rest 服务(网络组件 -> 改造)。
我仍然对向我的演示者注入 Rest 服务感到困惑,因为我找到的所有示例都是向 activity 注入。
这是我的代码。
视图:
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");
}
作为主持人:
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);
}
这是我的 dagger2 代码
@CustomScope
@Component(modules = ApiModule.class, dependencies = NetworkComponent.class)
public interface ApiComponent {
MainActivity inject(MainActivity activity);
PageFragment inject(PageFragment fragment);
}
最佳做法是创建一个交互器 class 来处理此问题,然后将该交互器注入演示者中。在下面的项目中查看我的代码以了解。主持人代码是:
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();
}
}
});
}}
互动者是:
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();
}}
交互界面:
public interface PopularMoviesInteractor {
Observable<Movie[]> loadPopularMovies(int page, int limit);
void onDestroy();}
并在您的模块中写入:
@Provides
public PopularMoviesInteractor provideInteractor(PopularMoviesInteractorImpl interactor) {
return interactor;}
交互器是通过构造注入提供的。(不过你可以通过简单的注入来实现)
这里是 mvp 的一个干净的例子:
http://github.com/mmirhoseini/fyber_mobile_offers
我看到这个问题已经有人回答了。但是如果你想要一个关于如何在 MVP 架构中使用依赖注入的清晰示例,我真的建议你检查这个 boilerplate 因为它完全基于使用 Dagger2 的 DI 并且它遵循 MVP 架构。
样板当前处理的依赖项如下:
- 数据库依赖:封装了所有的数据库操作。
- 共享偏好依赖:处理共享偏好。
- 本地文件依赖:处理保存文件。
- 分析依赖:涵盖向分析后端报告事件的所有操作(GA、Segment、FB、Flurry ..)
- 日志依赖:封装所有与日志相关的操作到您的控制台
- Api依赖:封装了所有API相关操作
依赖注入的强大功能非常方便,尤其是对于测试而言,因为您可以轻松地将测试环境中的依赖项切换为虚拟依赖项。
我想问一下MVP和dagger的工作方式。所以,在 android 开发中,我们知道 Activity 和 fragment 是一个视图,我们通过实现观察者来制作演示者(在我的例子中,我使用 rxjava + retrofit)。在这种情况下,我使用匕首来注入 Rest 服务(网络组件 -> 改造)。
我仍然对向我的演示者注入 Rest 服务感到困惑,因为我找到的所有示例都是向 activity 注入。
这是我的代码。
视图:
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");
}
作为主持人:
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);
}
这是我的 dagger2 代码
@CustomScope
@Component(modules = ApiModule.class, dependencies = NetworkComponent.class)
public interface ApiComponent {
MainActivity inject(MainActivity activity);
PageFragment inject(PageFragment fragment);
}
最佳做法是创建一个交互器 class 来处理此问题,然后将该交互器注入演示者中。在下面的项目中查看我的代码以了解。主持人代码是:
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();
}
}
});
}}
互动者是:
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();
}}
交互界面:
public interface PopularMoviesInteractor {
Observable<Movie[]> loadPopularMovies(int page, int limit);
void onDestroy();}
并在您的模块中写入:
@Provides
public PopularMoviesInteractor provideInteractor(PopularMoviesInteractorImpl interactor) {
return interactor;}
交互器是通过构造注入提供的。(不过你可以通过简单的注入来实现)
这里是 mvp 的一个干净的例子: http://github.com/mmirhoseini/fyber_mobile_offers
我看到这个问题已经有人回答了。但是如果你想要一个关于如何在 MVP 架构中使用依赖注入的清晰示例,我真的建议你检查这个 boilerplate 因为它完全基于使用 Dagger2 的 DI 并且它遵循 MVP 架构。
样板当前处理的依赖项如下:
- 数据库依赖:封装了所有的数据库操作。
- 共享偏好依赖:处理共享偏好。
- 本地文件依赖:处理保存文件。
- 分析依赖:涵盖向分析后端报告事件的所有操作(GA、Segment、FB、Flurry ..)
- 日志依赖:封装所有与日志相关的操作到您的控制台
- Api依赖:封装了所有API相关操作
依赖注入的强大功能非常方便,尤其是对于测试而言,因为您可以轻松地将测试环境中的依赖项切换为虚拟依赖项。