Android開(kāi)發(fā)之Dagger2--MVP模式中使用(四)

前言

在上一篇文章里Android開(kāi)發(fā)之Dagger2--Module&Component(三),主要分析了Dagger2注入過(guò)程,Module和Component各有什么作用,使用的例子也是很簡(jiǎn)單的。前面曾經(jīng)提到過(guò),Dagger2最適合在mvp模式中使用,那這位篇文章就是應(yīng)用在mvp模式中。對(duì)mvp模式不了解的可以參照 Android架構(gòu)--MVC、MVP、MVVM ,MVP模式--登錄,這一篇文章就是在第二篇文章的基礎(chǔ)上引入了Dager2。

廢話不說(shuō),直接上代碼 源碼傳送門(mén)

代碼

1 .View

mvp模式的view部分,我把它放在一個(gè)接口里面,當(dāng)然可以單獨(dú)為登錄模塊寫(xiě)一個(gè)View接口,考慮到每個(gè)界面有可能都會(huì)有個(gè)View接口,所以我把它們放在一個(gè)IView接口里,這樣可以減少接口文件的數(shù)量。
view的主要作用是
1.接收用戶請(qǐng)求,并把請(qǐng)求傳遞給Presenter層處理。
2.Presenter操作View層更新數(shù)據(jù)

  • 對(duì)于登錄模塊來(lái)說(shuō),getUserName(),getPassWord()方法分別是接收用戶名和密碼的,屬于接收用戶請(qǐng)求部分,在Presenter里這兩個(gè)方法會(huì)被調(diào)用,實(shí)現(xiàn)將用戶請(qǐng)求傳遞給Presenter層。
  • closeDispose(Disposable disposable),toOtherActivity()方法則是數(shù)據(jù)請(qǐng)求成功后,Presenter操作View層進(jìn)行數(shù)據(jù)更新
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模塊實(shí)現(xiàn)的,不同于在傳統(tǒng)的MVC模式,在MVC模式里,Activity既是View層,又是Model層,在MVP里,Activity則完全充當(dāng)了View的角色。
所以在要Activity里實(shí)現(xiàn)ILoginView 接口。

public class LoginActivity extends BaseActivity implements IView.ILoginView {
}
2. Model

Model層的作用如下:

  • 接受Presenter的請(qǐng)求進(jìn)行數(shù)據(jù)更新
  • 更新完成后通知Presenter數(shù)據(jù)更新完畢,Presenter再去通知View進(jìn)行界面更新
    很明顯,Model層就是數(shù)據(jù)請(qǐng)求的層。
    我同樣所有的Model都放在IModel類里面,IModel文件里的一個(gè)接口就對(duì)應(yīng)著一個(gè)Model模塊的網(wǎng)絡(luò)請(qǐng)求方法,方便對(duì)醒目里的所有網(wǎng)絡(luò)請(qǐng)求進(jìn)行管理。
    很明顯,登錄模塊的Model就只有一個(gè)請(qǐng)求登錄的方法,對(duì)于通知Presenter層數(shù)據(jù)更新完畢,則是通過(guò)接口回調(diào)的方式。
public class IModel {

    /**
     * 登錄
     */
    public interface ILoginModel {
        void login(LoginBody loginBody, MyCallBack<UserLoginBean> callBack); //登錄
    }

}

通過(guò)接口回調(diào)通知Presenter數(shù)據(jù)已更新完畢。

public interface MyCallBack<T> {
    void onSuccess(T response);         //成功回調(diào)
    void onError(String header,String message);   //失敗回調(diào)
    void onDispose(Disposable disposable);   // 切斷上有發(fā)送事件
}

對(duì)于登錄模塊,要有登錄模塊的Model繼承自IModel里對(duì)應(yīng)的接口。

public class LoginModel implements IModel.ILoginModel {

    /**
     * 構(gòu)造方法
     *
     * @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銷毀時(shí)停止執(zhí)行
                        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", "服務(wù)器異常,請(qǐng)稍后再試");
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
}
3.Presenter

Presenter層的作用:

  • 操作Model進(jìn)行數(shù)據(jù)更新
  • 操作View層進(jìn)行界面更新
    Presenter層實(shí)際起到的是個(gè)類似的中介作用,所以在Presenter層里有對(duì)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里,通過(guò)下面的代碼引入

 LoginPresenter mLoginPresenter = new LoginPresenter(this);

通過(guò) mLoginPresenter.login()在Activity里執(zhí)行登錄方法。

上面mvp模式時(shí)沒(méi)有引進(jìn)Dagger2的時(shí)候,下面引進(jìn)Dagger2。

1.首次分析一下需要Inject哪個(gè)對(duì)象。

  • 在Activity里持有了一個(gè)LoginPresenter 對(duì)象的引用,傳入的是一個(gè)IView.ILoginView,通過(guò)IView.ILoginView,LoginPresenter 實(shí)現(xiàn)從Activity接接受請(qǐng)求,請(qǐng)求成功后通知Activity更新界面。所以這個(gè)LoginPresenter 可以通過(guò)Inject的形式注入。
LoginPresenter mLoginPresenter = new LoginPresenter(this);
  • 在LoginPresenter里,構(gòu)造方法里有個(gè)LoginModel對(duì)象,所以也是可以注入的。
public LoginPresenter(IView.ILoginView iLoginView) {
        this.mILoginView = iLoginView;
        mLoginModel = new LoginModel();
    }

所以LoginActivity里修改代碼如下:

 @Inject
    LoginPresenter mLoginPresenter;

LoginPresenter里修改代碼如下:

 @Inject
    LoginModel mLoginModel;

2. Module

前文說(shuō)過(guò),Module是提供依賴的,要提供@Provides注解的以provide開(kāi)頭的方法。
上面說(shuō)過(guò),我們需要提供的是LoginPresenter和LoginModel的對(duì)象。
但是在提供LoginPresenter對(duì)象的時(shí)候,發(fā)現(xiàn)它需要一個(gè)IView.ILoginView的對(duì)象,所以我們還要用過(guò)IView.ILoginView的對(duì)象。
所以這里我們要提供三個(gè)依賴。
在這里補(bǔ)充一下當(dāng)遇到@Inject注解的時(shí)候處理步驟:

1. 查找Module中是否有創(chuàng)建該類的方法
2. 若存在創(chuàng)建該類的方法,查看該方法是否有參數(shù)
    2.1 有參數(shù),實(shí)例化該類,并且從  步驟1  開(kāi)始初始化每個(gè)參數(shù)
    2.2  沒(méi)有參數(shù),直接實(shí)例化該類,一次注入完成
3. 不存在創(chuàng)建該類的方法,查找Inject注解的構(gòu)造函數(shù),看構(gòu)造函數(shù)是否存在參數(shù)
    3.1:若存在參數(shù),則  步驟1   開(kāi)始依次初始化每個(gè)參數(shù)
    3.2:若不存在參數(shù),則直接初始化該類實(shí)例,一次依賴注入完成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有兩個(gè)構(gòu)造方法,因?yàn)樽⑷氲紸ctivity是需要參數(shù)的,而注入到LoginPresenter是不需要參數(shù)的。

3.Component

Component 是聯(lián)系inject和Module的橋梁,習(xí)慣稱為注入器

@Singleton
@Component(modules = {LoginModule.class})
public interface LoginComponent {

    void inject(LoginActivity loginActivity);
    void inject(LoginPresenter loginPresenter);

}

4.執(zhí)行注入

在Activity里添加代碼

 DaggerLoginComponent.builder()
                .loginModule(new LoginModule(this))
                .build()
                .inject(this);

在LoginPresenter里添加代碼

 DaggerLoginComponent.builder()
                .loginModule(new LoginModule())
                .build()
                .inject(this);

編譯執(zhí)行,即可看到效果


源碼傳送門(mén)

目前我們接觸到的Dagger2的注解符,有@Inject @Module @Provide @Component等,其實(shí)Dagger2還有其他的注解符,比如 @Singleton(其實(shí)前面代碼有了),@Scope @Qualifier等,下一篇文章簡(jiǎn)要介紹一下。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容