前言
在上一篇文章里Android开发之Dagger2--Module&Component(三),主要分析了Dagger2注入过程,Module和Component各有什么作用,使用的例子也是很简单的。前面曾经提到过,Dagger2最适合在mvp模式中使用,那这位篇文章就是应用在mvp模式中。对mvp模式不了解的可以参照 Android架构--MVC、MVP、MVVM ,MVP模式--登录,这一篇文章就是在第二篇文章的基础上引入了Dager2。
废话不说,直接上代码 源码传送门
代码
1 .View
mvp模式的view部分,我把它放在一个接口里面,当然可以单独为登录模块写一个View接口,考虑到每个界面有可能都会有个View接口,所以我把它们放在一个IView接口里,这样可以减少接口文件的数量。
view的主要作用是
1.接收用户请求,并把请求传递给Presenter层处理。
2.Presenter操作View层更新数据
- 对于登录模块来说,getUserName(),getPassWord()方法分别是接收用户名和密码的,属于接收用户请求部分,在Presenter里这两个方法会被调用,实现将用户请求传递给Presenter层。
- closeDispose(Disposable disposable),toOtherActivity()方法则是数据请求成功后,Presenter操作View层进行数据更新
public class IView {
/**
* 登录
*/
public interface ILoginView {
String getUserName();
String getPassWord();
void showToast(String content);
void closeDispose(Disposable disposable);
void showProgress();
void hideProgress();
void toOtherActivity();
}
}
ILoginView 接口里定义的方法,最终是要在View模块实现的,不同于在传统的MVC模式,在MVC模式里,Activity既是View层,又是Model层,在MVP里,Activity则完全充当了View的角色。
所以在要Activity里实现ILoginView 接口。
public class LoginActivity extends BaseActivity implements IView.ILoginView {
}
2. Model
Model层的作用如下:
- 接受Presenter的请求进行数据更新
- 更新完成后通知Presenter数据更新完毕,Presenter再去通知View进行界面更新
很明显,Model层就是数据请求的层。
我同样所有的Model都放在IModel类里面,IModel文件里的一个接口就对应着一个Model模块的网络请求方法,方便对醒目里的所有网络请求进行管理。
很明显,登录模块的Model就只有一个请求登录的方法,对于通知Presenter层数据更新完毕,则是通过接口回调的方式。
public class IModel {
/**
* 登录
*/
public interface ILoginModel {
void login(LoginBody loginBody, MyCallBack<UserLoginBean> callBack); //登录
}
}
通过接口回调通知Presenter数据已更新完毕。
public interface MyCallBack<T> {
void onSuccess(T response); //成功回调
void onError(String header,String message); //失败回调
void onDispose(Disposable disposable); // 切断上有发送事件
}
对于登录模块,要有登录模块的Model继承自IModel里对应的接口。
public class LoginModel implements IModel.ILoginModel {
/**
* 构造方法
*
* @param
*/
@Override
public void login(LoginBody loginBody, final MyCallBack<UserLoginBean> callBack) {
JsNetworkService.getInstance().getIJsNetworkService()
.getLogin(loginBody)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<UserLoginBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
Disposable mDisposable; //用于Activity销毁时停止执行
mDisposable = d;
callBack.onDispose(mDisposable);
}
@Override
public void onNext(@NonNull UserLoginBean userLoginBean) {
callBack.onSuccess(userLoginBean);
}
@Override
public void onError(@NonNull Throwable e) {
callBack.onError("Server Error", "服务器异常,请稍后再试");
}
@Override
public void onComplete() {
}
});
}
}
3.Presenter
Presenter层的作用:
- 操作Model进行数据更新
- 操作View层进行界面更新
Presenter层实际起到的是个类似的中介作用,所以在Presenter层里有对View和Model的引用。
public class LoginPresenter {
private IView.ILoginView mILoginView;
private LoginModel mLoginModel;
public LoginPresenter(IView.ILoginView iLoginView) {
this.mILoginView = iLoginView;
mLoginModel = new LoginModel();
}
/**
* 登录
*/
public void login() {
mILoginView.showProgress();
LoginBody loginBody = new LoginBody(mILoginView.getPassWord(), mILoginView.getUserName());
mLoginModel.login(loginBody, new MyCallBack<UserLoginBean>() {
@Override
public void onSuccess(UserLoginBean userLoginBean) {
mILoginView.hideProgress();
if (userLoginBean.getStatus().equals("1")) {
mILoginView.toOtherActivity();
}
mILoginView.showToast(userLoginBean.getMessage());
}
@Override
public void onError(String header, String message) {
mILoginView.hideProgress();
mILoginView.showToast(message);
}
@Override
public void onDispose(Disposable disposable) {
mILoginView.closeDispose(disposable);
}
});
/* mLoginModel.login(loginBody, new MyCallBack.OnLoginListener() {
@Override
public void loginSuccess(UserLoginBean userLoginBean) {
mILoginView.showToast(userLoginBean.getMessage());
}
@Override
public void loginFailed(String header, String message) {
}
@Override
public void dispose(Disposable disposable) {
mILoginView.closeDispose(disposable);
}
});*/
}
}
然后再Activity里,通过下面的代码引入
LoginPresenter mLoginPresenter = new LoginPresenter(this);
通过 mLoginPresenter.login()在Activity里执行登录方法。
上面mvp模式时没有引进Dagger2的时候,下面引进Dagger2。
1.首次分析一下需要Inject哪个对象。
- 在Activity里持有了一个LoginPresenter 对象的引用,传入的是一个IView.ILoginView,通过IView.ILoginView,LoginPresenter 实现从Activity接接受请求,请求成功后通知Activity更新界面。所以这个LoginPresenter 可以通过Inject的形式注入。
LoginPresenter mLoginPresenter = new LoginPresenter(this);
- 在LoginPresenter里,构造方法里有个LoginModel对象,所以也是可以注入的。
public LoginPresenter(IView.ILoginView iLoginView) {
this.mILoginView = iLoginView;
mLoginModel = new LoginModel();
}
所以LoginActivity里修改代码如下:
@Inject
LoginPresenter mLoginPresenter;
LoginPresenter里修改代码如下:
@Inject
LoginModel mLoginModel;
2. Module
前文说过,Module是提供依赖的,要提供@Provides注解的以provide开头的方法。
上面说过,我们需要提供的是LoginPresenter和LoginModel的对象。
但是在提供LoginPresenter对象的时候,发现它需要一个IView.ILoginView的对象,所以我们还要用过IView.ILoginView的对象。
所以这里我们要提供三个依赖。
在这里补充一下当遇到@Inject注解的时候处理步骤:
1. 查找Module中是否有创建该类的方法
2. 若存在创建该类的方法,查看该方法是否有参数
2.1 有参数,实例化该类,并且从 步骤1 开始初始化每个参数
2.2 没有参数,直接实例化该类,一次注入完成
3. 不存在创建该类的方法,查找Inject注解的构造函数,看构造函数是否存在参数
3.1:若存在参数,则 步骤1 开始依次初始化每个参数
3.2:若不存在参数,则直接初始化该类实例,一次依赖注入完成0
所以Module的代码为
@Module
public class LoginModule {
private IView.ILoginView loginView;
public LoginModule(){
}
public LoginModule(IView.ILoginView view){
this.loginView=view;
}
/**
* 提供LoginPresenter
* @param iLoginView
* @return
*/
@Provides
@Singleton
LoginPresenter provideLoginPresenter(IView.ILoginView iLoginView){
return new LoginPresenter(iLoginView);
}
@Provides
@Singleton
IView.ILoginView provideILoginView(){
return loginView;
}
@Provides
@Singleton
LoginModel provideLoginModel(){
return new LoginModel();
}
}
这里提一下,LoginModule有两个构造方法,因为注入到Activity是需要参数的,而注入到LoginPresenter是不需要参数的。
3.Component
Component 是联系inject和Module的桥梁,习惯称为注入器
@Singleton
@Component(modules = {LoginModule.class})
public interface LoginComponent {
void inject(LoginActivity loginActivity);
void inject(LoginPresenter loginPresenter);
}
4.执行注入
在Activity里添加代码
DaggerLoginComponent.builder()
.loginModule(new LoginModule(this))
.build()
.inject(this);
在LoginPresenter里添加代码
DaggerLoginComponent.builder()
.loginModule(new LoginModule())
.build()
.inject(this);
编译执行,即可看到效果
源码传送门
目前我们接触到的Dagger2的注解符,有@Inject @Module @Provide @Component等,其实Dagger2还有其他的注解符,比如 @Singleton(其实前面代码有了),@Scope @Qualifier等,下一篇文章简要介绍一下。