個人博客:haichenyi.com。感謝關(guān)注
??接著上一篇簡單的框架,沒有看過的同鞋可以去喵一眼。上一篇我們搭好了簡單的框架,初始化一次的內(nèi)容丟在Application里面,所有的activity繼承一個類BaseActivity,還有Fragment繼承的一個類BaseFragment
??現(xiàn)在我們來加上MVP,不懂MVP的同鞋可以看一下,我前面寫過的三種主流框架的對比。我們先導(dǎo)入dagger2的兩個包,代碼如下:
implementation 'com.google.dagger:dagger:2.14.1'
annotationProcessor "com.google.dagger:dagger-compiler:2.14.1"
第一步
??新建BasePresenter接口,BaseMvpPresenter類去實現(xiàn)BasePresenter接口,代碼如下
package com.shfzwkeji.smartwardrobe.base;
/**
* Author: 海晨憶.
* Date: 2017/12/21
* Desc: 不帶mvp的presenter的基類
*/
public interface BasePresenter<T extends BaseView> {
void attachView(T baseView);
void detachView();
}
package com.haichenyi.myproject.base;
/**
* Author: 海晨憶
* Date: 2018/2/23
* Desc:帶mvp的presenter的基類
*/
public class BaseMvpPresenter<T extends BaseView> implements BasePresenter<T> {
protected T baseView;
@Override
public void attachView(T baseView) {
this.baseView = baseView;
}
@Override
public void detachView() {
this.baseView = null;
}
}
??這里就只有兩個方法,一個是綁定view,還有一個是在ondestory方法里面解除綁定的方法,用來保證P層的生命周期和V層同步,避免了,當(dāng)V層銷毀的時候,P層仍然存在造成的內(nèi)存泄漏。
第二步
??新建BaseMvpActivity
package com.haichenyi.myproject.base;
import javax.inject.Inject;
/**
* Author: 海晨憶
* Date: 2018/2/23
* Desc:帶MVP的Activity
*/
public abstract class BaseMvpActivity<T extends BasePresenter> extends BaseActivity{
@Inject
protected T basePresenter;
@Override
@SuppressWarnings("unchecked")
protected void initView() {
super.initView();
initInject();
if (null != basePresenter) {
basePresenter.attachView(this);
}
}
protected abstract void initInject();
@Override
protected void onDestroy() {
if (null != basePresenter) {
basePresenter.detachView();
basePresenter = null;
}
super.onDestroy();
}
}
??運用dagger2注解的方式,生成P層,這里我們在用P層之前得先生成P層,所以initject方法一定要在basePresenter用之前調(diào)用,因為他就是生成P層的代碼。
??怎么生成呢?dagger我們一般都命名成di層,所以,我們先創(chuàng)建di層的package,項目結(jié)構(gòu)圖如下:

??這里給出的是mvp+dagger加入之后的項目結(jié)構(gòu)。我們重點看選中的di層,里面有4個package分別是component,module,qualifier,scope四個包,至于他們的作用分別是什么,請自行百度,google,dagger的用法。我這里先貼出這幾個類,接口的代碼:
ActivityComponent
package com.haichenyi.myproject.di.component;
import com.haichenyi.myproject.MainActivity;
import com.haichenyi.myproject.di.module.ActivityModule;
import com.haichenyi.myproject.di.scope.ActivityScope;
import dagger.Component;
/**
* Author: 海晨憶
* Date: 2018/2/23
* Desc:
*/
@ActivityScope
@Component(dependencies = AppComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
void inject(MainActivity mainActivity);
}
AppComponent
package com.haichenyi.myproject.di.component;
import com.haichenyi.myproject.di.module.AppModule;
import com.haichenyi.myproject.di.module.HttpModule;
import javax.inject.Singleton;
import dagger.Component;
/**
* Author: 海晨憶
* Date: 2018/2/23
* Desc:
*/
@Singleton
@Component(modules = {AppModule.class, HttpModule.class})
public interface AppComponent {
}
ActivityModule
package com.haichenyi.myproject.di.module;
import dagger.Module;
/**
* Author: 海晨憶
* Date: 2018/2/23
* Desc:
*/
@Module
public class ActivityModule {
}
AppModule
package com.haichenyi.myproject.di.module;
import com.haichenyi.myproject.base.MyApplication;
import dagger.Module;
/**
* Author: 海晨憶
* Date: 2018/2/23
* Desc:
*/
@Module
public class AppModule {
private MyApplication application;
public AppModule(MyApplication application) {
this.application = application;
}
}
HttpModule
package com.haichenyi.myproject.di.module;
import dagger.Module;
/**
* Author: 海晨憶
* Date: 2018/2/23
* Desc:
*/
@Module
public class HttpModule {
}
ActivityScope
package com.haichenyi.myproject.di.scope;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Scope;
/**
* Author: 海晨憶
* Date: 2018/2/23
* Desc:
*/
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}
??這幾個類,接口里面基本上都沒有內(nèi)容,因為這幾個類都是后面才會用的到的,這里我直接貼出來,說起來方便一些。還需要加兩個方法,在MyApplication里面加如下方法:
/**
* 獲取AppComponent.
*
* @return AppComponent
*/
public static synchronized AppComponent getAppComponent() {
if (null == appComponent) {
appComponent = DaggerAppComponent.builder()
.appModule(new AppModule(getInstance()))
.httpModule(new HttpModule())
.build();
}
return appComponent;
}
在BaseActivity里面加如下方法:
protected ActivityComponent getActivityComponent() {
return DaggerActivityComponent.builder()
.appComponent(MyApplication.getAppComponent())
.activityModule(new ActivityModule())
.build();
}
??加完這兩個方法之后,肯定會有錯誤提示,重新編譯一遍項目就可以了,如果重新編譯一遍,還是不行,請重新對比一下,哪里不一樣。
第三步
??就是關(guān)于mvp的了,從上面圖應(yīng)該看到了,有一個presenter包,和contract包,我們之前有一篇博客講過,MVP就是多了很多個接口,這些接口寫在哪呢?就在contract層
MainContract 代碼如下:
package com.haichenyi.myproject.contract;
import com.haichenyi.myproject.base.BasePresenter;
import com.haichenyi.myproject.base.BaseView;
/**
* Author: 海晨憶
* Date: 2018/2/23
* Desc:
*/
public interface MainContract {
interface IView extends BaseView{
}
interface Presenter extends BasePresenter<IView>{
void loadData();
}
}
??這里我需要說明的就是Presenter接口繼承的是IVew,不是BaseView,頁面變化的方法都是在IView接口里面定義,邏輯處理,網(wǎng)絡(luò)請求方法都是在Presenter接口里面定義
MainPresenter 代碼如下
package com.haichenyi.myproject.presenter;
import com.haichenyi.myproject.base.BaseMvpPresenter;
import com.haichenyi.myproject.contract.MainContract;
import javax.inject.Inject;
/**
* Author: 海晨憶
* Date: 2018/2/23
* Desc:
*/
public class MainPresenter extends BaseMvpPresenter<MainContract.IView>
implements MainContract.Presenter {
@Inject
MainPresenter() {
}
@Override
public void loadData() {
baseView.showTipMsg("加載數(shù)據(jù)");
}
}
??這里我需要說明的是注意繼承BaseMvpPresenter傳的是MainContract.IView,不是BaseView,實現(xiàn)MainContract.Presenter接口,還有一點就是注意構(gòu)造方法,上面有注解,這里的loadData里面應(yīng)該是我們的網(wǎng)絡(luò)請求邏輯,這里我放到后面一篇在說,這里我先就直接Toast,表示走了這個方法
第四步
??就是MainActivity,這里我貼出代碼
package com.haichenyi.myproject;
import android.os.Bundle;
import com.haichenyi.myproject.base.BaseMvpActivity;
import com.haichenyi.myproject.contract.MainContract;
import com.haichenyi.myproject.presenter.MainPresenter;
public class MainActivity extends BaseMvpActivity<MainPresenter> implements MainContract.IView {
@Override
protected int getLayoutId(Bundle savedInstanceState) {
return R.layout.activity_main;
}
@Override
protected void initData() {
super.initData();
initToolbar(true, false, true).setMyTitle("主頁").setMoreTitle("更多");
basePresenter.loadData();
}
@Override
protected void initInject() {
getActivityComponent().inject(this);
}
}
??這里我需要說明的是繼承BaseMvpActivity,泛型直接傳MainPresenter,然后,實現(xiàn)MainContract.IView接口,直接用basePresenter調(diào)用方法,需要實現(xiàn)initInject方法,只要是是繼承BaseMvpActivity的activity,都需要在ActivityComponent()里面注冊一邊。比方說,LoginActivity也是繼承的BaseMvpActivity,辣么,在di層的component包下面的ActivityComponent接口里面定義一個方法
void inject(LoginActivity loginActivity);
在LoginActivity的initInject方法里面寫同樣的代碼
getActivityComponent().inject(this);
就像這樣寫就可以了。
總結(jié)
??寫到這里,mvp+dagger2基本上完成了,MVP的目的就是解藕,把業(yè)務(wù)邏輯,網(wǎng)絡(luò)請求丟在P層,頁面不發(fā)生變化,就只用改P層邏輯,從而達到了解藕的目的。dagger2簡化了代碼,并且,它有著全局單例模式,和局部單例模式,優(yōu)化了我們的內(nèi)存,減少了內(nèi)存浪費。不用每次都去new一個P層對象出來。下一篇,我們就把網(wǎng)絡(luò)請求加上