Android應(yīng)用中MVP最佳實踐

所謂MVP(Model-View-Presenter)模式。是將APP的結(jié)構(gòu)分為三層:

view - UI顯示層

view 層主要負責(zé):

  1. 提供UI交互
  2. 在presenter的控制下修改UI。
  3. 將業(yè)務(wù)事件交由presenter處理励饵。
    注意. View層不存儲數(shù)據(jù)筛圆,不與Model層交互决摧。

presenter - 邏輯處理層

presenter 層主要負責(zé):

  1. 對UI的各種業(yè)務(wù)事件進行相應(yīng)處理政基。也許是與Model層交互思杯,也許自己進行一些計算胜蛉,也許控制后臺Task,Servic
  2. 對各種訂閱事件進行響應(yīng),修改UI誊册。
  3. 臨時存儲頁面相關(guān)數(shù)據(jù)领突。
    注意. Presenter內(nèi)不出現(xiàn)View引用。

model - 數(shù)據(jù)層

model層主要負責(zé):

  1. 從網(wǎng)絡(luò)案怯,數(shù)據(jù)庫君旦,文件,傳感器殴泰,第三方等數(shù)據(jù)源讀寫數(shù)據(jù)于宙。
  2. 對外部的數(shù)據(jù)類型進行解析轉(zhuǎn)換為APP內(nèi)部數(shù)據(jù)交由上層處理。
  3. 對數(shù)據(jù)的臨時存儲,管理悍汛,協(xié)調(diào)上層數(shù)據(jù)請求捞魁。

如圖示,里面的activity离咐,presenter谱俭,model均為例子:

mvp
mvp

將復(fù)雜的功能分割為各層內(nèi)的小問題。各層內(nèi)功能單一宵蛀。這樣易于功能修改拓展與Debug昆著。
解耦的設(shè)計,獨立的模塊术陶,更有利于分工開發(fā)與測試凑懂。

Activity的異常重啟

Activity會在少數(shù)情況下被系統(tǒng)重啟:

當用戶旋轉(zhuǎn)屏幕
在后臺時內(nèi)存不足
改變語言設(shè)置
attache 一個外部顯示器等。

正確的方式應(yīng)該是:
Presenter與Activity的綁定關(guān)系應(yīng)由靜態(tài)類管理梧宫。而不是由Activity管理接谨。當Activity意外重啟時Presenter不應(yīng)重啟。Activity重啟時塘匣,Presenter與Activity重新綁定脓豪,根據(jù)數(shù)據(jù)恢復(fù)Activity狀態(tài)。
而當Activity真正銷毀時忌卤。對應(yīng)Presenter才應(yīng)該跟隨銷毀扫夜。

當內(nèi)存不足時,Activity被銷毀其實是整個進程被銷毀驰徊。所以Presenter也無能為力笤闯。還原時需要重建Presenter。

生命周期

Activity是一個上帝類棍厂,其實不適合作為View颗味。所以有些MVP方案將Activity作為Presenter。最主要在于他的生命周期牽扯太多邏輯處理業(yè)務(wù)勋桶。這些由Presenter負責(zé)的話情況可以改善很多脱衙。我建議將在頂級父類中將activity的生命周期在Presenter中實現(xiàn)一遍,然后生命周期有關(guān)的業(yè)務(wù)邏輯直接由Presenter來實現(xiàn)例驹。

Model的初始化

Model不僅僅是javabean捐韩。Model是負責(zé)提供各類數(shù)據(jù)模型。在此基礎(chǔ)上我將Model拓展為數(shù)據(jù)層提供數(shù)據(jù)交互鹃锈。將javabean單獨為數(shù)據(jù)層的一部分荤胁。
Model層的各個Model一般使用單例。這樣的好處在于這個唯一對象可以管理一些數(shù)據(jù)供所有上層使用屎债。
Model的單例對象

public class UserModel extends AbsModel{
     public static UserModel getInstance() { 
       return getInstance(UserModel.class);    
    }
        @Override
    protected void onAppCreate(Context ctx) {
        super.onAppCreate(ctx);
        //初始化
    }

    public void login(String number,String password,DataCallback<UserDetail> callback){
        //進行登錄請求與回調(diào)仅政,并保存返回賬號
    }
    public void register(String tel,String password,String code,int gender,String nickname,StatusCallback callback){
        //進行注冊請求與回調(diào)
    }

    public void findPassword(String number,String code,String password,DataCallback<User> callback){
         //進行找回密碼請求與回調(diào)
    }

    public void certification(String number,String school,String realName,String stuCard,DataCallback<User> callback){
         //進行認證請求與回調(diào)
    }

    public void LoginOut(){
        //登出操作
    }

}

既然Model層管理數(shù)據(jù),并且是單例盆驹。他就有初始化的需求圆丹,比如在APP啟動時就請求數(shù)據(jù),記錄信息躯喇,開始一個后臺線程與服務(wù)器同步信息等辫封。這些操作與Presenter無關(guān)。是數(shù)據(jù)層自發(fā)的的功能廉丽。所以需要在Application啟動時進行Model的初始化倦微。
但又要注意不能在Application的onCreate()進行過多操作,否則會啟動時間過長正压。所以可考慮在啟動時創(chuàng)建一個后臺線程欣福,將即時性不強的初始化操作放到后臺線程。

Adapter的處理

對于Adapter是放在View好還是Presenter好焦履,這個問題確實難以解決拓劝。但在使用解耦的ViewHolder后這個問題便很明了。視圖的創(chuàng)建與改變?nèi)蒝iewHolder管理裁良。然后Adapter僅僅處理面向ViewHolder的邏輯凿将。
然后ViewHolder屬于View,Adapter屬于Presenter价脾。參考EasyRecyclerView
Adapter:

public class PersonAdapter extends RecyclerArrayAdapter<Person> {
    public PersonAdapter(Context context) {
        super(context);
    }

    @Override
    public BaseViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) {
        return new PersonViewHolder(parent);
    }
}

ViewHolder:

public class PersonViewHolder extends BaseViewHolder<Person> {
    private TextView mTv_name;
    private SimpleDraweeView mImg_face;
    private TextView mTv_sign;


    public PersonViewHolder(ViewGroup parent) {
        super(parent,R.layout.item_person);
        mTv_name = $(R.id.person_name);
        mTv_sign = $(R.id.person_sign);
        mImg_face = $(R.id.person_face);
    }

    @Override
    public void setData(final Person person){
        mTv_name.setText(person.getName());
        mTv_sign.setText(person.getSign());
        mImg_face.setImageURI(Uri.parse(person.getFace()));
    }
}

Rx的參與

Rx訂閱發(fā)布模式在MVP中作用很大牧抵。可以極大簡化層間通訊的處理侨把。View向Presenter訂閱數(shù)據(jù)犀变。Presenter可以向Model層訂閱數(shù)據(jù)。形成一個數(shù)據(jù)鏈秋柄。數(shù)據(jù)可以直接鏈式到達View層获枝。優(yōu)雅易拓展。
Presenter

public class QuestionShowPresenter extends BeamDataActivityPresenter<QuestionShowActivity,Question> {

    @Override
    protected void onCreate(QuestionShowActivity view, Bundle savedState) {
        super.onCreate(view, savedState);
        QuestionModel.getInstance().getQuestion(1).subscribe(this);
    }
}

View

public class QuestionShowActivity extends BeamDataActivity<QuestionShowPresenter,Question> {
    @Override
    public void setData(Question data) {
        //顯示數(shù)據(jù)
    }

    @Override
    public void setError(Throwable e) {
        //顯示錯誤
    }
}

Beam

Beam是我做的一套基于MVP模式的快速開發(fā)框架骇笔。參考了nucleus省店。上面的示例代碼都是使用了這個(為方便復(fù)制的這個框架demo代碼.= =)嚣崭。定義了一套開發(fā)規(guī)范。并提供了基于這套規(guī)范的Activity懦傍,F(xiàn)ragment雹舀,Presenter,Model等父類及控件和API等粗俱,完成APP開發(fā)過程中大量繁瑣工作说榆。并進行了一系列優(yōu)化。詳情看這里

示例

豆逼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末寸认,一起剝皮案震驚了整個濱河市签财,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌偏塞,老刑警劉巖唱蒸,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異灸叼,居然都是意外死亡油宜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門怜姿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來慎冤,“玉大人,你說我怎么就攤上這事沧卢∫系蹋” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵但狭,是天一觀的道長披诗。 經(jīng)常有香客問我,道長立磁,這世上最難降的妖魔是什么呈队? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮唱歧,結(jié)果婚禮上宪摧,老公的妹妹穿的比我還像新娘。我一直安慰自己颅崩,他們只是感情好几于,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著沿后,像睡著了一般沿彭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上尖滚,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天喉刘,我揣著相機與錄音瞧柔,去河邊找鬼。 笑死睦裳,一個胖子當著我的面吹牛非剃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播推沸,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼券坞!你這毒婦竟也來了鬓催?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤恨锚,失蹤者是張志新(化名)和其女友劉穎宇驾,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猴伶,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡课舍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了他挎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片筝尾。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖办桨,靈堂內(nèi)的尸體忽然破棺而出筹淫,到底是詐尸還是另有隱情,我是刑警寧澤呢撞,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布损姜,位于F島的核電站,受9級特大地震影響殊霞,放射性物質(zhì)發(fā)生泄漏摧阅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一绷蹲、第九天 我趴在偏房一處隱蔽的房頂上張望棒卷。 院中可真熱鬧,春花似錦祝钢、人聲如沸娇跟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽苞俘。三九已至,卻和暖如春龄章,著一層夾襖步出監(jiān)牢的瞬間吃谣,已是汗流浹背乞封。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留岗憋,地道東北人肃晚。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像仔戈,于是被迫代替她去往敵國和親关串。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容