Android 架構選型 (MVP+DataBinding)

經過代碼對比,詳細講解MVC,MVP,MVVM之間應該如何選擇,以及對Android單元測試的探索。本文的側重點在於如何選擇,並無對每種架構模式概念展開詳解(網絡上這方面的文章有不少,你們能夠自行搜索)。java

大綱

  • MVC or MVP or MVVM?
  • 肯定選型:MVP + DataBinding
  • 單元測試(探索階段)

目的

  • 提升開發效率
  • 易於測試
  • 擁抱變化
  • 下降維護成本

Android中的MVC

示例:

展現任務詳情的功能,詳情View層的經過xml來寫的,請求數據相關的代碼會在Model層提供接口,而後經過Activity對View和Model層進行鏈接。android

代碼:

M:
public interface TaskModel {
    void loadTask(String taskId, OnTaskListener listener);
}

V:
taskdetail.xml:界面佈局文件,採用XML進行描述,屬於V層的一部分。

C & V:
TaskDetailActivity:C層和V層
public class TaskDetailActivity {
    private void initView() {
        taskModel.loadTask(taskId, new OnTaskListener() {
            public void onSuccess(Task task) {
                //V層代碼,可是目前耦合到了C層 
                detailTitle.setText(task.getTitle);
            }
        });
    }  
}複製代碼

總結:

  • 編寫簡單快速,適合含有簡單邏輯的業務,或是demo程序。
  • Activity的臃腫:xml做爲view層,控制能力太弱,沒法動態的改變頁面的內容,只能把代碼寫在activity中,形成了activity既是Controller層,又是View層的問題。
  • 耦合度較高,需求變化改動大,後續維護成本高。
  • Controller混雜着Android代碼沒法Junit。

Android中的MVP

示例:

展現任務詳情的功能,詳情View層的經過xml和Activity來完成,請求數據相關的代碼會在Model層提供接口,而後經過Presenter對View和Model層進行鏈接。編程

代碼:

M:
public interface TaskModel { 
    void loadTask(String taskId, OnTaskListener listener);
}

V:
taskdetail.xml:界面佈局文件,採用XML進行描述,屬於V層的一部分。
public class TaskDetailActivity implements TaskDetailView {
    public void showTask(Task task) {
        detailTitle.setText(task.getTitle);
    }  
}

P:
public class TaskDetailPresenter implements Presenter {
    public void getTask() {
        taskModel.loadTask(taskId, new OnTaskListener() {
            public void onSuccess(Task task) {
                //經過接口回調到V層更新UI
                taskDetailView.showTask(task);
            }
        });
    }  
}複製代碼

總結:

  • 減小各層之間耦合,易於後續的需求變化,下降維護成本。
  • Presenter層獨立於Android代碼以外,能夠進行Junit測試。
  • 接口和類較多,互相作回調,代碼臃腫。
  • Presenter層與View層是經過接口進行交互的,接口粒度很差控制。

Android中的MVVM

示例:

展現任務詳情的功能,詳情View層的經過xml和Activity來完成,請求數據相關的代碼會在Model層提供接口,而後經過ViewModel對View和Model層進行鏈接。網絡

代碼:

M:
public interface TaskModel ... void loadTask(String taskId, OnTaskListener listener);
V:
taskdetail.xml:界面佈局文件,採用XML進行描述,綁定規則在xml中進行定義。
TaskDetailActivity:Activity主要是初始化和補充的功能。
VM:
TaskDetailViewModel {
        public void getTask() {
              taskModel.loadTask(taskId, new OnTaskListener() {
                    public void onSuccess(Task task) {
                        //經過綁定技術更新UI,作到數據獨立於UI
                        taskDeatailViewBinding.setTask(task);
            }
              });
        }  
}複製代碼

總結:

  • 和MVP比較像,主要區別在於View和ViewModel / Presenter之間的通訊
  • 相比MVP優點是經過DataBinding技術爲VM和V層進行數據綁定,提升開發效率,因爲目前綁定技術的侷限,V層一些界面的處理仍是須要Activity的輔助。
  • VM層摻雜Android代碼沒法進行Junit測試。

肯定選型

經過以上對比,選擇了MVP+DataBinding,此架構模式基於MVP,並使用DataBinding庫來顯示數據並綁定View。它並不遵循嚴格的MVVM或MVP模式,由於它同時使用了ViewModel和Presenter。架構

DataBinding

這是我上篇文章咱們爲何要使用DataBinding,裏面經過代碼的對比,總結說明爲何要使用DataBinding的技術,有興趣的同窗能夠閱讀一下,在這裏我把文章裏的一小段總結貼出來:mvc

DataBinding爲數據驅動:數據變化後自動更新UI;事件處理:直接找到目標實例處理用戶操做的事件。這樣咱們就不須要和UI或者控件打交道,只須要在java代碼中處理業務邏輯就行了,很是清晰,其他的統一交給binding庫去完成。下降了代碼耦合度,使得數據獨立於UI,對之後程序的變化和維護都有積極的影響。框架

MVP+DataBinding

示例:

展現任務詳情的功能,數據和事件綁定與基礎MVP代碼的對比。mvvm

代碼:

//普通MVP 任務詳情代碼示例:
public void onCreateView(...) {
    detailTitle = (TextView) root.findViewById(R.id.task_detail_title);
    detailComplete = (CheckBox) root.findViewById(R.id.task_detail_complete);
    detailComplete.setOnCheckedChangeListener(
           (cb, isChecked) -> presenter.completeChanged(task, isChecked)
    );
}
@Override
public void showDescription(String title) {
    detailTitle.setText(title);
}
//xml文件省略...

//MVP+DataBinding 任務詳情代碼示例:
@Override
public void showTask(Task task) {
    viewDataBinding.setTask(task);
}
//能夠經過佈局文件直接綁定到數據模型的屬性(xml文件)
<TextView
    android:id="@+id/task_detail_title"
    android:text="@{task.title}" />
//事件綁定一樣能夠直接在佈局文件中實現(xml文件)
<CheckBox
    android:id="@+id/task_detail_complete"
    android:checked="@{task.completed}"
    android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />複製代碼

總結:

  • DataBinding庫提升了開發效率,使得xml佈局文件用於將數據綁定到UI元素,也能夠綁定一個action handler(Presenter)處理用戶操做的事件,能夠觀察和設置數據,以便在須要時自動更新(雙向綁定)。
  • 須要對View和Presenter兩層作測試,增長工做量。
  • 目前Android Studio對Databing的支持不是太好(報錯和代碼自動生成)

單元測試(探索階段)

Presenter

不須要Android環境,所以使用Junit測試便可 ide

  • JUnit:Java語言的單元測試框架
  • Mockito:模擬對象的測試框架

View

使用Google建議的Espresso進行UI的測試(須要依賴Android環境)佈局

  • AndroidJUnitRunner:Android 且與 JUnit 4 兼容的測試運行器
  • Espresso:功能性 UI 測試框架

問題

就目前實踐過程當中,會發現須要爲測試寫一些額外的方法,不是太舒服。而且寫兩層測試,工做量變大。還有覆蓋率以及維護的問題,一直在探索最佳實踐,會在之後的文章裏面和你們分享。

本片文章來自於本身的編程實戰,寫的很差的地方請你們幫忙指正,但願能幫助你們選到合適本身的架構模式。謝謝閱讀。

相關文章
相關標籤/搜索