上一篇我們大致了解了項(xiàng)目的結(jié)構(gòu)組成,這一篇我們來(lái)分別說(shuō)說(shuō)里面的細(xì)節(jié)。
首先,搭建框架,就要根據(jù)框架的特點(diǎn)去完成初步的搭建。根據(jù)MVP的官網(wǎng)描述,我們首先完成MVP框架的基礎(chǔ)構(gòu)建,每一個(gè)activity都是一個(gè)V,一個(gè)V對(duì)應(yīng)一個(gè)PResenter,所以在每一個(gè)界面的包下面,就至少包含了三個(gè)文件,IXXXConstane(V、P接口描述類)、XXXActivity(V)、XXXPresenter(P),每一個(gè)類的職責(zé)也必須清晰,XXXActivity主要用來(lái)作顯示界面使用,不能包含任何邏輯,XXXPresenter主要用來(lái)溝通數(shù)據(jù)模塊和V,數(shù)據(jù)改變了,就應(yīng)該通知相應(yīng)的界面控件進(jìn)行改變,這是MVP框架中很重要的思想,每一個(gè)模塊都只是完成自己的功能,不能逾越。
來(lái)看代碼,在每一個(gè)V中都持有P的引用,那么在V中是可以調(diào)用P中的邏輯的,但我們一般不這么做,在V中持有P的引用,我們只是為了初始化P,讓P和V關(guān)聯(lián)起來(lái),而不是直接去調(diào)用P中的邏輯,這點(diǎn)比較重要,不然結(jié)構(gòu)就比較混亂了。比如在MainActivity中,就持有IMainConstane.IMainPresenter的引用,但我們一般不直接調(diào)用IMainPresenter中的邏輯:
public class MainActivity extends BaseActivity implements IMainConstane.IMainView { @Inject IMainConstane.IMainPresenter mMainPresenter; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.text); DaggerMainComponent.builder() .userModelComponent(((Myapplication) getApplicationContext()).getUserModelComponent()) .mainModule(new MainModule(this)) .build() .inject(this); } public void onViewClick(View view) { switch (view.getId()) { case R.id.login: // 這里打印一下用戶模塊對(duì)象的地址,來(lái)判斷@Singleton單利模式是否有用 mMainPresenter.logUserHashcode(); mMainPresenter.login("", ""); break; case R.id.view_detail: startActivity(new Intent(getApplicationContext(), SecondActivity.class)); break; } } @Override public void setTextMessage(String message) { if (TextUtils.isEmpty(message)) { tv.setText(""); } else { tv.setText(message); } }} 可以看到,我在V中,是沒有直接調(diào)用P中的邏輯代碼的,但有一種情況例外,就是事件交互,在人機(jī)進(jìn)行交互的過程中,我們需要進(jìn)行一些數(shù)據(jù)的操作,這個(gè)時(shí)候直接調(diào)用是沒問題的。
我所說(shuō)的只是“最好不要在V中直接調(diào)用P的代碼,并不是一定不能,V中調(diào)用P的代碼會(huì)顯得結(jié)構(gòu)層次有點(diǎn)亂,但如果業(yè)務(wù)需要,那也沒辦法”
看完V,我們?cè)賮?lái)說(shuō)說(shuō)P,P的構(gòu)造函數(shù)中就傳遞進(jìn)來(lái)兩個(gè)參數(shù),分別為M和V,這也就是為什么P是整個(gè)框架的邏輯處理核心的原因了,因?yàn)橥瑫r(shí)持有兩者,那么就可以使用兩者暴露出來(lái)的接口進(jìn)行整個(gè)邏輯的操作和判斷了。
public class MainPresenter implements IMainConstane.IMainPresenter { private final IMainConstane.IMainView mView; private final IUserModel mUserModel; public MainPresenter(IMainConstane.IMainView view, IUserModel usermodel) { this.mView = view; this.mUserModel = usermodel; } @Override public void login(String userName, String passWord) { mUserModel.login(userName, password, new OnLoginListener() { @Override public void loginSuccess() { mView.setTextMessage("login Success"); } @Override public void loginFaile(String message) { mView.setTextMessage("login Faile"); } }); } @Override public void logUserHashcode() { mUserModel.logUser(); mUserModel.logOkHttp(); mUserModel.logRetrofit(); }} 看上面的代碼,當(dāng)界面點(diǎn)擊之后,會(huì)調(diào)用P中的login方法,也就是上面的login方法了,而該方法中則調(diào)用的是數(shù)據(jù)模塊中的登錄方法,我們跟進(jìn)去看一下,就會(huì)發(fā)現(xiàn)調(diào)用到了UserModelImpl里面的登錄方法,這樣,整個(gè)邏輯就很清楚了,界面發(fā)起數(shù)據(jù)請(qǐng)求,通過P轉(zhuǎn)到數(shù)據(jù)層,數(shù)據(jù)層通過回調(diào)接口(OnLoginListener)回調(diào)給P,然后P再根據(jù)持有的V進(jìn)行界面的更改,也就是
mView.setTextMessage("login Success");和mView.setTextMessage("login Faile"); 其實(shí)在這里是有一個(gè)歧義和區(qū)別的,你可能注意到了model包下的otherModel,它代表的是你項(xiàng)目中除用戶數(shù)據(jù)模塊之外的其它數(shù)據(jù)模塊,比如我應(yīng)用里面還需要產(chǎn)品數(shù)據(jù)模塊,那么在P中如何將這些數(shù)據(jù)模塊傳遞進(jìn)去呢?
總不能修改P的構(gòu)造函數(shù),將所有數(shù)據(jù)模塊依次傳遞進(jìn)去吧?這樣做先不說(shuō)修改構(gòu)造函數(shù)有多么繁瑣,就算有dagger2我也不推薦這樣使用。
我覺得,數(shù)據(jù)模塊因該統(tǒng)一一個(gè)入口,然后里面應(yīng)該分別持有所需模塊,然后將統(tǒng)一入口提供給P。當(dāng)然,這只是我想的,每個(gè)人對(duì)這個(gè)地方的處理可能不一樣,有些人喜歡分別傳入,也有些人喜歡統(tǒng)一入口方便管理,這就看個(gè)人喜好了!
最好還想看一下數(shù)據(jù)模塊的組成的,但看了一下,覺得沒什么好說(shuō)的,代碼寫的很詳細(xì)也簡(jiǎn)單易懂,主要就是接口編程,一個(gè)接口類IUserModel,一個(gè)實(shí)現(xiàn)類UserModelImpl。
這個(gè)地方不明白的可以私聊我!
源碼下載
詳細(xì)的Dagger2+MVP融合,一行一行分析,一點(diǎn)一點(diǎn)進(jìn)步,之一
詳細(xì)的Dagger2+MVP融合,一行一行分析,一點(diǎn)一點(diǎn)進(jìn)步,之三
詳細(xì)的Dagger2+MVP融合,一行一行分析,一點(diǎn)一點(diǎn)進(jìn)步,之四
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注