前言
在上一篇文章里Android開發(fā)之Dagger2--Module&Component(三),主要分析了Dagger2注入過程现横,Module和Component各有什么作用漓拾,使用的例子也是很簡單的。前面曾經(jīng)提到過戒祠,Dagger2最適合在mvp模式中使用骇两,那這位篇文章就是應用在mvp模式中。對mvp模式不了解的可以參照 Android架構(gòu)--MVC姜盈、MVP低千、MVVM ,MVP模式--登錄馏颂,這一篇文章就是在第二篇文章的基礎上引入了Dager2示血。
廢話不說,直接上代碼 源碼傳送門
代碼
1 .View
mvp模式的view部分救拉,我把它放在一個接口里面难审,當然可以單獨為登錄模塊寫一個View接口,考慮到每個界面有可能都會有個View接口亿絮,所以我把它們放在一個IView接口里告喊,這樣可以減少接口文件的數(shù)量。
view的主要作用是
1.接收用戶請求派昧,并把請求傳遞給Presenter層處理葱绒。
2.Presenter操作View層更新數(shù)據(jù)
- 對于登錄模塊來說,getUserName()斗锭,getPassWord()方法分別是接收用戶名和密碼的,屬于接收用戶請求部分失球,在Presenter里這兩個方法會被調(diào)用岖是,實現(xiàn)將用戶請求傳遞給Presenter層。
- closeDispose(Disposable disposable)实苞,toOtherActivity()方法則是數(shù)據(jù)請求成功后豺撑,Presenter操作View層進行數(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模塊實現(xiàn)的黔牵,不同于在傳統(tǒng)的MVC模式聪轿,在MVC模式里,Activity既是View層猾浦,又是Model層陆错,在MVP里灯抛,Activity則完全充當了View的角色。
所以在要Activity里實現(xiàn)ILoginView 接口音瓷。
public class LoginActivity extends BaseActivity implements IView.ILoginView {
}
2. Model
Model層的作用如下:
- 接受Presenter的請求進行數(shù)據(jù)更新
- 更新完成后通知Presenter數(shù)據(jù)更新完畢对嚼,Presenter再去通知View進行界面更新
很明顯,Model層就是數(shù)據(jù)請求的層绳慎。
我同樣所有的Model都放在IModel類里面纵竖,IModel文件里的一個接口就對應著一個Model模塊的網(wǎng)絡請求方法,方便對醒目里的所有網(wǎng)絡請求進行管理杏愤。
很明顯靡砌,登錄模塊的Model就只有一個請求登錄的方法,對于通知Presenter層數(shù)據(jù)更新完畢珊楼,則是通過接口回調(diào)的方式通殃。
public class IModel {
/**
* 登錄
*/
public interface ILoginModel {
void login(LoginBody loginBody, MyCallBack<UserLoginBean> callBack); //登錄
}
}
通過接口回調(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ā)送事件
}
對于登錄模塊亥曹,要有登錄模塊的Model繼承自IModel里對應的接口邓了。
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銷毀時停止執(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", "服務器異常,請稍后再試");
}
@Override
public void onComplete() {
}
});
}
}
3.Presenter
Presenter層的作用:
- 操作Model進行數(shù)據(jù)更新
- 操作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里執(zhí)行登錄方法蛇受。
上面mvp模式時沒有引進Dagger2的時候句葵,下面引進Dagger2。
1.首次分析一下需要Inject哪個對象兢仰。
- 在Activity里持有了一個LoginPresenter 對象的引用乍丈,傳入的是一個IView.ILoginView,通過IView.ILoginView把将,LoginPresenter 實現(xiàn)從Activity接接受請求轻专,請求成功后通知Activity更新界面。所以這個LoginPresenter 可以通過Inject的形式注入察蹲。
LoginPresenter mLoginPresenter = new LoginPresenter(this);
- 在LoginPresenter里请垛,構(gòu)造方法里有個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對象的時候,發(fā)現(xiàn)它需要一個IView.ILoginView的對象匈勋,所以我們還要用過IView.ILoginView的對象礼旅。
所以這里我們要提供三個依賴。
在這里補充一下當遇到@Inject注解的時候處理步驟:
1. 查找Module中是否有創(chuàng)建該類的方法
2. 若存在創(chuàng)建該類的方法颓影,查看該方法是否有參數(shù)
2.1 有參數(shù)各淀,實例化該類,并且從 步驟1 開始初始化每個參數(shù)
2.2 沒有參數(shù)诡挂,直接實例化該類碎浇,一次注入完成
3. 不存在創(chuàng)建該類的方法,查找Inject注解的構(gòu)造函數(shù)璃俗,看構(gòu)造函數(shù)是否存在參數(shù)
3.1:若存在參數(shù)奴璃,則 步驟1 開始依次初始化每個參數(shù)
3.2:若不存在參數(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òu)造方法,因為注入到Activity是需要參數(shù)的唱星,而注入到LoginPresenter是不需要參數(shù)的雳旅。
3.Component
Component 是聯(lián)系inject和Module的橋梁,習慣稱為注入器
@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í)行间聊,即可看到效果
源碼傳送門
目前我們接觸到的Dagger2的注解符攒盈,有@Inject @Module @Provide @Component等,其實Dagger2還有其他的注解符哎榴,比如 @Singleton(其實前面代碼有了)型豁,@Scope @Qualifier等,下一篇文章簡要介紹一下尚蝌。