Android開發(fā)中的MVC_MVP_MVVM

為什么要學習MVC

需求(查詢用戶賬號信息):

用戶輸入賬號,點擊按鈕可進行查詢賬號信息,如果查詢數(shù)據(jù)成功,則將數(shù)據(jù)展示在界面上;如果查詢數(shù)據(jù)失敗,則在界面上提示獲取數(shù)據(jù)失敗。

不實用框架實現(xiàn)需求

創(chuàng)建一個Activity,實現(xiàn)它的所有功能(獲取用戶輸入信息,展示獲取信息成功界面,展示獲取信息失敗界面,查詢用戶數(shù)據(jù),業(yè)務邏輯)。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText edittext;
    private Button button;
    private TextView text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        init();
    }

    private void init() {
        edittext = findViewById(R.id.edittext);
        button = findViewById(R.id.button);
        button.setOnClickListener(this);
        text = findViewById(R.id.text);
    }

    @Override
    public void onClick(View v) {
        String userInput = getUserInput();
        getAccountData(userInput, new MCallBack() {
            @Override
            public void onSuccess(Account account) {
                showSuccessPage(account);
            }

            @Override
            public void onFail() {
                showFailPage();
            }
        });
    }

    //獲取用戶輸入信息
    private String getUserInput() {
        return edittext.getText().toString().trim();
    }

    //展示獲取信息成功界面
    private void showSuccessPage(Account account) {
        text.setText("用戶賬號:" + account.getName() + "|" + "用戶等級:" + account.getLevel());
    }

    //展示獲取信息失敗界面
    private void showFailPage() {
        text.setText("獲取數(shù)據(jù)失敗");
    }

    //查詢用戶數(shù)據(jù)
    private void getAccountData(String accountName, MCallBack mCallBack) {
        Random random = new Random();
        boolean isSuccess = random.nextBoolean();
        if (isSuccess) {
            Account account = new Account();
            account.setName(accountName);
            account.setLevel(100);
            mCallBack.onSuccess(account);
        } else {
            mCallBack.onFail();
        }
    }
}

由上述代碼可以發(fā)現(xiàn),MainActivity承載了太多的功能,既要實現(xiàn)方法,又要承擔邏輯,這樣當以后功能越來越多的時候,這個界面的代碼就會越來越多,越來越臃腫。

MVC模型簡介

MVC的全名是Model View Controller,即模型(Model)-視圖(View)-控制器(Controller)。
Controller:Activity,Fragment
View:layout,View控件
Controller:數(shù)據(jù)處理(網(wǎng)絡請求,SQL等)


WX20191121-161628.png

使用MVC實現(xiàn)需求

MVCActivity(C層):業(yè)務邏輯處理,獲取用戶輸入,展示成功界面,展示失敗界面
MVCModel(M層):查詢賬號數(shù)據(jù)
View(V層):layout
1.將數(shù)據(jù)的獲取和界面的展示分離(將查詢賬號數(shù)據(jù)從Activity中分離到Model中即可)
2.解決各層之間的通信問題(Activity通知Model獲取數(shù)據(jù),Model通知Activity更新界面)

public class MVCActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText edittext;
    private Button button;
    private TextView text;
    private MVCModel mvcModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        init();
    }


    private void init() {
        edittext = findViewById(R.id.edittext);
        button = findViewById(R.id.button);
        button.setOnClickListener(this);
        text = findViewById(R.id.text);
        mvcModel = new MVCModel();
    }

    @Override
    public void onClick(View v) {
        mvcModel.getAccountData(getUserInput(), new MCallBack() {
            @Override
            public void onSuccess(Account account) {
                showSuccessPage(account);
            }

            @Override
            public void onFail() {
                showFailPage();
            }
        });
    }

    //獲取用戶輸入信息
    private String getUserInput() {
        return edittext.getText().toString().trim();
    }

    //展示獲取信息成功界面
    private void showSuccessPage(Account account) {
        text.setText("用戶賬號:" + account.getName() + "|" + "用戶等級:" + account.getLevel());
    }

    //展示獲取信息失敗界面
    private void showFailPage() {
        text.setText("獲取數(shù)據(jù)失敗");
    }
}
public class MVCModel {
    //查詢用戶數(shù)據(jù)
    public void getAccountData(String accountName, MCallBack mCallBack) {
        Random random = new Random();
        boolean isSuccess = random.nextBoolean();
        if (isSuccess) {
            Account account = new Account();
            account.setName(accountName);
            account.setLevel(100);
            mCallBack.onSuccess(account);
        } else {
            mCallBack.onFail();
        }
    }
}

MVC優(yōu)缺點

優(yōu)點:一定程度上實現(xiàn)了Model與View的分離,降低了代碼的耦合性。

缺點:Controller與View難以完全解耦,并且隨著項目復雜度的提升,因為Controller還承擔部分業(yè)務邏輯,所以Controller將越來越臃腫。

MVP模型簡介

MVP即Model_View_Presenter模型


WX20191121-161412.png

MVP與MVC的差別

1.Model與View不再直接進行通信,而是通過中間層Presenter來實現(xiàn)。

  1. Activity的功能被簡化,不再充當控制器,主要負責View層面的工作。

MVP代碼實戰(zhàn)

WX20191121-162447.png

使用MVP實現(xiàn)需求

  1. MVPActivity負責提供View層面的功能(采用實現(xiàn)接口的方式)

2.MVPModel負責提供數(shù)據(jù)方面的功能

3.Model與View不再直接通信,通過Presenter來實現(xiàn)

public class MVPActivity extends AppCompatActivity implements View.OnClickListener, IMVPView {

    private EditText edittext;
    private Button button;
    private TextView text;
    private MVPPresenter mvpPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        init();
    }

    private void init() {
        edittext = findViewById(R.id.edittext);
        button = findViewById(R.id.button);
        button.setOnClickListener(this);
        text = findViewById(R.id.text);
        mvpPresenter = new MVPPresenter(this);
    }

    @Override
    public void onClick(View v) {

        mvpPresenter.getData(getUserInput());
    }

    @Override
    public String getUserInput() {
        return edittext.getText().toString().trim();
    }

    @Override
    public void showSuccessPage(Account account) {
        text.setText("用戶賬號:" + account.getName() + "|" + "用戶等級:" + account.getLevel());
    }

    @Override
    public void showFailPage() {
        text.setText("獲取數(shù)據(jù)失敗");
    }
}
public interface IMVPView {

    String getUserInput();

    void showSuccessPage(Account account);

    void showFailPage();
}

public class MVPModel {
    //查詢用戶數(shù)據(jù)
    public void getAccountData(String accountName, MCallBack mCallBack) {
        Random random = new Random();
        boolean isSuccess = random.nextBoolean();
        if (isSuccess) {
            Account account = new Account();
            account.setName(accountName);
            account.setLevel(100);
            mCallBack.onSuccess(account);
        } else {
            mCallBack.onFail();
        }
    }
}

public class MVPPresenter {
    private IMVPView imvpView;
    private MVPModel mvpModel;

    public MVPPresenter(IMVPView imvpView) {
        this.imvpView = imvpView;
        mvpModel = new MVPModel();
    }

    public void getData(String accountName) {
        mvpModel.getAccountData(accountName, new MCallBack() {
            @Override
            public void onSuccess(Account account) {
                imvpView.showSuccessPage(account);
            }

            @Override
            public void onFail() {
                imvpView.showFailPage();
            }
        });
    }

}
 

MVP優(yōu)缺點

優(yōu)點:解決了MVC中Controller與View過度耦合的缺點,職責劃分明顯,更加易于維護。

缺點:接口數(shù)量多,項目復雜度升高。隨著項目復雜度的提升,Presenter層將越來越臃腫。

使用MVP的建議

1.接口規(guī)范化(封裝父類接口以減少接口的使用量)
2.使用第三方插件自動生成MVP代碼
3.對于一些簡單的界面,可以選擇不使用框架
4.根據(jù)項目復雜程度,部分模塊可以選擇不使用接口

MVVM模型簡介

WX20191121-165818.png

MVVM是Model-View-ViewModel的簡寫,MVVM在MVP的基礎上實現(xiàn)了數(shù)據(jù)視圖的綁定(DataBinding),當數(shù)據(jù)變化時,視圖會自動更新;反之,當視圖發(fā)生變化時,數(shù)據(jù)也會自動更新。
1.減少了接口數(shù)量
2.告別繁瑣findViewById操作

DataBinding是什么

DataBinding是谷歌官方發(fā)布的一個實現(xiàn)數(shù)據(jù)綁定的框架(實現(xiàn)數(shù)據(jù)與視圖雙向綁定),DataBinding可以幫助我們在安卓中更好的實現(xiàn)MVVM模式。

DataBinding使用步驟

1.啟用DataBinding
2.修改布局文件為DataBinding布局
3.數(shù)據(jù)綁定

使用MVVM實現(xiàn)需求

WX20191126-155005.png

1.提供View,ViewModel以及Model三層
2.將布局修改為DataBinding布局

  1. View與ViewModel之間通過DataBinding進行通信
  2. 獲取數(shù)據(jù)并展示在界面上
public class MVVMActivity extends AppCompatActivity {

    private MVVMViewModel mvvmViewModel;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMvvmBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_mvvm);
        mvvmViewModel = new MVVMViewModel(getApplication(),binding);
        binding.setViewModel(mvvmViewModel);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="viewModel"
            type="com.test.myapplication.mvvm.MVVMViewModel"/>
    </data>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <EditText
            android:id="@+id/edittext"
            android:text="@={viewModel.userInput}"
            android:hint="請輸入要查詢的賬號"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <Button
            android:layout_gravity="center"
            android:id="@+id/button"
            android:text="獲取賬號信息"
            android:onClick="@{viewModel.getData}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/text"
            android:layout_marginTop="50dp"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{viewModel.result}"
            android:hint="賬號信息未獲取" />
    </LinearLayout>
</layout>
public class MVVMViewModel extends BaseObservable {

    private String result;
    private String userInput;
    private MVVMModel model;
    private ActivityMvvmBinding binding;

    //一般需要傳入Application對象,方便在ViewModel中使用application
    //比如sharepreferences
    public MVVMViewModel(Application application) {
        model = new MVVMModel();
    }

    public MVVMViewModel(Application application, ActivityMvvmBinding binding) {
        model = new MVVMModel();
        this.binding = binding;
    }

    public void getData(View view) {

        model.getAccountData(userInput, new MCallBack() {
            @Override
            public void onSuccess(Account account) {
                String info = "用戶賬號:" + account.getName() + "|" + "用戶等級:" + account.getLevel();
                setResult(info);
            }

            @Override
            public void onFail() {
                setResult("獲取數(shù)據(jù)失敗");
            }
        });
    }

    @Bindable
    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
        notifyPropertyChanged(BR.result);
    }

    @Bindable
    public String getUserInput() {
        return userInput;
    }

    public void setUserInput(String userInput) {
        this.userInput = userInput;
        notifyPropertyChanged(BR.userInput);
    }
}
public class MVVMModel {
    //查詢用戶數(shù)據(jù)
    public void getAccountData(String accountName, MCallBack mCallBack) {
        Random random = new Random();
        boolean isSuccess = random.nextBoolean();
        if (isSuccess) {
            Account account = new Account();
            account.setName(accountName);
            account.setLevel(100);
            mCallBack.onSuccess(account);
        } else {
            mCallBack.onFail();
        }
    }
}

MVVM優(yōu)缺點

優(yōu)點:實現(xiàn)了數(shù)據(jù)和視圖的雙向綁定,極大的簡化代碼。

缺點:bug難以調試,并且DataBinding目前還存在一些編譯問題。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容