.MVP模式簡介
我們的目標(biāo)是實(shí)現(xiàn)MVP模式來開發(fā)我們的應(yīng)用陡厘,那首先得知道什么是MVP模式。下面這篇文章講述得通俗易懂诡宗,非常適合新手學(xué)習(xí)要拂。MVP模式簡單易懂介紹
這里簡單講一下,
M ---- model术奖,即數(shù)據(jù)層
V ---- view礁遵,即界面層比如我們的Activity和Fragment
P ---- presenter, 即業(yè)務(wù)層匿辩,我個(gè)人覺得更像是管理層。管理數(shù)據(jù)如何顯示榛丢,管理界面如何改變數(shù)據(jù)铲球。
這樣一來就可以避免我們的Activity承擔(dān)過多的工作,樓主之前開發(fā)中有一個(gè)Activity的代碼量到達(dá)了兩千行晰赞,一碰到那部分需求有變更我就頭大<诓 !掖鱼!真是往事不堪回首然走。。戏挡。
MVP作為一種相對新興的架構(gòu)芍瑞,要理解它也需要花一點(diǎn)點(diǎn)時(shí)間的。大家最好還是去讀一下上面提到的那篇文章褐墅,不然這篇文章你可能會懵b拆檬。。妥凳。
2.Dagger簡介
dagger的核心是依賴和注入竟贯。目的是為了讓View層與Presenter層盡可能的解耦。至于解耦的好處逝钥,無論是測試還是后續(xù)擴(kuò)展功能等方面都是受益無窮的屑那。
通俗的講就是,當(dāng)你在Activity中需要使用一個(gè)類的對象P時(shí)候艘款,你不用管P的對象如何實(shí)例化持际,直接就拿來用。至于這個(gè)P如何實(shí)例化哗咆,dagger會幫你搞定蜘欲,只要你按照它的套路來就行了。
樓主學(xué)習(xí)dagger也是看了網(wǎng)上很多文章岳枷,終于在讀完這篇dagger2頓悟之后才開竅了芒填。推薦大家去讀讀呜叫,里面講得很詳細(xì)從實(shí)現(xiàn)到源碼分析都有涉及空繁。所以,那篇文章里面寫過的東西我不打算再搬運(yùn)一遍了朱庆。
既然那篇文章已經(jīng)寫得那么好了盛泡,為什么我這里又要寫一篇呢?
一來樓主看了很多篇文章都很懵B娱颊,當(dāng)時(shí)就暗暗決定懂了之后一定要自己總結(jié)一番
二來每個(gè)人的思考方式都不同傲诵,說不定有些人思維方式跟我差不多凯砍,那么我的總結(jié)就更對他們的胃口,可以少走彎路了拴竹。
好了悟衩,廢話講完,來看例子栓拜。
3.使用dagger的實(shí)例
這是一個(gè)很小的mvp項(xiàng)目座泳,主要是講解一下dagger的使用流程。從這個(gè)項(xiàng)目中幕与,你是體會不到mvp的好處的挑势。
首先,需求是 點(diǎn)擊一個(gè)button啦鸣,程序就更新textView中的內(nèi)容潮饱。就像這樣:
其實(shí)實(shí)現(xiàn)這個(gè)功能,只需要短短幾句代碼就可以搞定的诫给。但是我們今天的目的是使用dagger香拉,所以先不忙,想想怎樣通過dagger來實(shí)現(xiàn)這個(gè)功能中狂。
3.1 引入dagger2到新建的項(xiàng)目
先在project的build.gradle文件中添加一個(gè)插件依賴 Android-apt
[java] view plain copy 在CODE上查看代碼片派生到我的代碼片
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
然后在app/build.gradle文件中添加dagger庫和相關(guān)依賴缕溉,下面是完整的app/build.gradle文件
[java] view plain copy 在CODE上查看代碼片派生到我的代碼片
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "k.javine.mvpprojectex"
minSdkVersion 19
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.google.dagger:dagger:2.2'
apt 'com.google.dagger:dagger-compiler:2.2'
compile 'org.glassfish:javax.annotation:10.0-b28'
compile 'com.jakewharton:butterknife:7.0.1'
}
大家注意頂部的
[java] view plain copy 在CODE上查看代碼片派生到我的代碼片
apply plugin: 'com.neenbedankt.android-apt'
和底部的
[java] view plain copy 在CODE上查看代碼片派生到我的代碼片
compile 'com.google.dagger:dagger:2.2'
apt 'com.google.dagger:dagger-compiler:2.2'
compile 'org.glassfish:javax.annotation:10.0-b28'
就可以了,我習(xí)慣性的使用了butterKnife庫吃型,本人非常喜歡這個(gè)東西证鸥。
好了,引入dagger2成功了勤晚。
3.2 項(xiàng)目結(jié)構(gòu)
簡單說一下:
a. IPresenter和IView兩個(gè)接口枉层,如果你了解了MVP模式就會明白它們的作用。主要是為了讓VIEW層和Presenter層的解耦
[java] view plain copy 在CODE上查看代碼片派生到我的代碼片
public interface IView {
/**
* 更新UI
* @param data
*/
void updateUi(String data);
}
[java] view plain copy 在CODE上查看代碼片派生到我的代碼片
public interface IPresenter {
/**
* 加載數(shù)據(jù)
*/
void loadData();
}
b. MyPresenter實(shí)現(xiàn)IPresenter接口(在此項(xiàng)目中IPresenter基本沒用到赐写,算我偷懶了),此類將被dagger注入到MainActivity中去鸟蜡。
[java] view plain copy 在CODE上查看代碼片派生到我的代碼片
public class MyPresenter implements IPresenter{
private IView mainView;
public MyPresenter(IView view){
mainView = view;
}
@Override
public void loadData() {
mainView.updateUi("Mvp Update UI "+System.currentTimeMillis());
}
}
c. MyModule類 用來提供依賴,里面定義一些用@Provides注解的以provide開頭的方法挺邀。MainActivity中使用的MyPresenter對象就是在此處被實(shí)例化的揉忘。
[java] view plain copy 在CODE上查看代碼片派生到我的代碼片
@Module
public class MyModule {
private IView mainView;
public MyModule(IView mainView){
this.mainView = mainView;
}
@Provides
public MyPresenter provideMyPresenter(){
return new MyPresenter(mainView);
}
}
d. AppComponent類是一種橋梁,MyPresenter類通過AppComponet注入到MainActivity中去的端铛。我們將會在MainActivity中看到注入是通過DaggerAppComponent類來執(zhí)行的泣矛,而這是一個(gè)我從來沒有編寫過的類...它就是dagger的插件給我們自動生成的,當(dāng)然是根據(jù)AppComponet來生成的禾蚕。
[java] view plain copy 在CODE上查看代碼片派生到我的代碼片
@Component(modules = MyModule.class)
public interface AppComponent {
void inject(MainActivity activity);
}
e. MainActivity實(shí)現(xiàn)IView接口您朽,這樣MyPresenter就可以通過IView引用實(shí)例來控制View層的改變。
[java] view plain copy 在CODE上查看代碼片派生到我的代碼片
public class MainActivity extends AppCompatActivity implements IView, View.OnClickListener {
@Bind(R.id.result)
TextView tv_result;
@Bind(R.id.btn_update)
Button btn_update;
@Inject
MyPresenter myPresenter; //獲取依賴的對象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
btn_update.setOnClickListener(this);
DaggerAppComponent.builder()
.myModule(new MyModule(this))
.build()
.inject(this); //注入
}
@Override
public void updateUi(String data) {
tv_result.setText(data);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_update:
myPresenter.loadData();
break;
}
}
}
每一步的代碼都很簡單换淆,最好是自己新建一個(gè)項(xiàng)目來跑一遍這個(gè)流程哗总。
這樣一來几颜,就算業(yè)務(wù)邏輯再復(fù)雜,都可以丟到presenter層去處理讯屈,activity只需要實(shí)現(xiàn)updateUi()方法和一些UI事件的處理即可蛋哭。
presenter層處理完數(shù)據(jù)之后,通過IView對象調(diào)用updateUi()方法將數(shù)據(jù)展示出來涮母。
樓主本人現(xiàn)在也是個(gè)MVP的初學(xué)者具壮,寫這篇文章的時(shí)候還有很多沒想明白的問題,有興趣可以一起討論討論哈蝇。
對了棺妓,dagger生成的代碼是值得去讀一讀的,可以幫助我們深入了解dagger的原理炮赦,位置在這里
注:圖中的MainActivity$$ViewBinder類是ButterKnife框架生成的怜跑。
2