Android开发之Dagger2--MVP模式中使用(四)

前言

在上一篇文章里Android开发之Dagger2--Module&Component(三),主要分析了Dagger2注入过程,Module和Component各有什么作用,使用的例子也是很简单的。前面曾经提到过,Dagger2最适合在mvp模式中使用,那这位篇文章就是应用在mvp模式中。对mvp模式不了解的可以参照 Android架构--MVC、MVP、MVVMMVP模式--登录,这一篇文章就是在第二篇文章的基础上引入了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等,下一篇文章简要介绍一下。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容