從零開始搭建MVP架構(gòu)

MVC、MVP概念網(wǎng)上都有,不再重復(fù),這里直接展示MVP架構(gòu)怎么搭建的。不考慮架構(gòu),正常我們寫的代碼一般都是MVC架構(gòu)的。以簡單的登錄界面為例:

public class MainActivity extends AppCompatActivity {
    private TextView tv_result;
    private EditText et_input;
    private Button btn_login;
    //進度條
    ProgressDialog progressDialog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_result = findViewById(R.id.tv_result);
        et_input = findViewById(R.id.et_input);
        btn_login = findViewById(R.id.btn_login);

        // 初始化進度條
        progressDialog = new ProgressDialog(this);
        progressDialog.setCancelable(false);

        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getData(et_input.getText().toString().trim());
            }
        });
    }
    /**
     * 模擬網(wǎng)絡(luò)請求
     * @param input
     */
    public void getData(final String input) {
        progressDialog.show();
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                switch (input) {
                    case "success":
                        tv_result.setText("登錄成功");
                        break;
                    case "fail":
                        tv_result.setText("請求失?。簠?shù)有誤");
                        break;
                    case "error":
                        tv_result.setText("請求報錯: 500");
                        break;
                }
                progressDialog.dismiss();
            }
        },1000);
    }
}

我們可以看到,UI處理、業(yè)務(wù)邏輯、數(shù)據(jù)請求都在一起,當(dāng)頁面邏輯越復(fù)雜時,我們activity中代碼越多,后面迭代維護時越麻煩,當(dāng)有邏輯相似的頁面時,我們還要重新寫一遍,造成代碼冗余,復(fù)用性差,這就需要用到我們的MVP架構(gòu),下面我們將代碼進行優(yōu)化:

先新建網(wǎng)絡(luò)請求的響應(yīng)

public interface IBaseCallback{

    /**
     * 數(shù)據(jù)請求成功
     * @param data 請求結(jié)果
     */
    void onSuccess(String data);

    /**
     * 網(wǎng)絡(luò)請求成功,但數(shù)據(jù)請求失敗(如參數(shù)錯誤,數(shù)據(jù)解析報錯,后臺報錯等)
     * @param msg  錯誤原因
     */
    void onFailure(String msg);

    /**
     * 網(wǎng)絡(luò)請求失敗
     * @param error 失敗原因
     */
    void onError(String error);

    /**
     * 當(dāng)請求數(shù)據(jù)結(jié)束時,無論結(jié)果如何,都會走的方法,一般用于加載框顯示隱藏控制
     */
    void onComplete();
}

將網(wǎng)絡(luò)請求單獨封裝成model

public class MvpModel {

    /**
     * 獲取網(wǎng)絡(luò)接口數(shù)據(jù)
     * @param param 請求參數(shù)
     * @param callback 數(shù)據(jù)回調(diào)接口
     */
    public static void getNetData(final String param, final IBaseCallback<String> callback){
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                switch (param){
                    case "success":
                        callback.onSuccess("登錄成功");
                        break;
                    case "fail":
                        callback.onFailure("請求失?。簠?shù)有誤");
                        break;
                    case "error":
                        callback.onError("請求報錯: 500");
                        break;
                }
                callback.onComplete();
            }
        },1000);
    }
}

創(chuàng)建Presenter進行業(yè)務(wù)邏輯處理

public class MvpPresenter  {
    private MvpView mvpView;
    /**
     * 獲取綁定的mvpView
     */
    public MvpView getMvpView() {
        return mvpView;
    }
    /**
     * 綁定view,一般在初始化中調(diào)用該方法,為避免網(wǎng)絡(luò)請求后view被銷
     * 毀造成空指針,所以將presenter與view綁定
     */
    public void attachView(MvpView mvpView) {
        this.mvpView = mvpView;
    }
    /**
     * 斷開view,一般在onDestroy中調(diào)用
     */
    public void detachView() {
        this.mvpView = null;
    }

    /**
     * 檢測是否與View建立連接,避免view被銷毀后空指針
     * 每次調(diào)用業(yè)務(wù)請求的時候都要出先調(diào)用方法檢查是否與View建立連接
     */
    public boolean isViewAttached() {
        return mvpView != null;
    }

    public void getData(String params) {
        getMvpView().showLoading();
        MvpModel.getNetData(params, new IBaseCallback<String>() {
            @Override
            public void onSuccess(String data) {
                if (isViewAttached())
                    getMvpView().showData(data);
            }

            @Override
            public void onFailure(String msg) {
                if (isViewAttached())
                    getMvpView().showFailureMessage(msg);
            }

            @Override
            public void onError(String error) {
                if (isViewAttached())
                    getMvpView().showErrorMessage(error);
            }

            @Override
            public void onComplete() {
                if (isViewAttached())
                    getMvpView().hideLoading();
            }
        });
    }
}

新建view的接口,然后用activity實現(xiàn)

public interface MvpView {

    /**
     * 當(dāng)數(shù)據(jù)請求成功后,調(diào)用此接口顯示數(shù)據(jù)
     */
    void showData(String data);

    /**
     * 當(dāng)網(wǎng)絡(luò)請求成功,但有其他報錯時后,調(diào)用此接口提示
     */
    void showFailureMessage(String msg);

    /**
     * 當(dāng)網(wǎng)絡(luò)請求失敗,調(diào)用此接口提示
     */
    void showErrorMessage(String error);

     /**
     * 顯示正在加載進度框
     */
    void showLoading();

    /**
     * 隱藏正在加載進度框
     */
    void hideLoading();
}
public class MainActivity extends AppCompatActivity implements MvpView{

    private TextView tv_result;
    private EditText et_input;
    private Button btn_login;
    MvpPresenter mvpPresenter;
    //進度條
    ProgressDialog progressDialog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_result = findViewById(R.id.tv_result);
        et_input = findViewById(R.id.et_input);
        btn_login = findViewById(R.id.btn_login);
        // 初始化進度條
        progressDialog = new ProgressDialog(this);
        progressDialog.setCancelable(false);
        mvpPresenter = new MvpPresenter();
        mvpPresenter.attachView(this);
        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mvpPresenter.getData(et_input.getText().toString().trim());
            }
        });
    }


    @Override
    public void showData(String data) {
        tv_result.setText(data);
    }

    @Override
    public void showFailureMessage(String msg) {
        tv_result.setText(msg);
    }

    @Override
    public void showErrorMessage(String error) {
        tv_result.setText(error);
    }
    @Override
    public void showLoading() {
        if (!progressDialog.isShowing()){
            progressDialog.show();
        }
    }

    @Override
    public void hideLoading() {
        if (progressDialog.isShowing()){
            progressDialog.dismiss();
        }
    }
}

這樣就將我們平常寫的MVC架構(gòu)的代碼,改為了MVP的,后面還可以將presenter抽取基類,view抽取基類,將代碼更簡化

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

相關(guān)閱讀更多精彩內(nèi)容

  • 雞湯:積跬步,至千里 本篇文章是從零開始搭建框架的第二章,將要講述的是flux架構(gòu)。 架構(gòu)簡述 關(guān)于架構(gòu),比較傳統(tǒng)...
    niknowzcd閱讀 3,313評論 5 15
  • 問題 在已經(jīng)開發(fā)過幾個項目的童鞋,如果這時需要重新開發(fā)一個新項目,是否需要自己重新搭建框架呢,還是從老項目中拷貝粘...
    8ba406212441閱讀 43,563評論 84 381
  • 個人博客:haichenyi.com。感謝關(guān)注 ??接著上一篇簡單的框架,沒有看過的同鞋可以去喵一眼。上一篇我們搭...
    海晨憶閱讀 939評論 0 4
  • 表情是什么,我認為表情就是表現(xiàn)出來的情緒。表情可以傳達很多信息。高興了當(dāng)然就笑了,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 129,618評論 2 7
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險厭惡者,不喜歡去冒險,但是人生放棄了冒險,也就放棄了無數(shù)的可能。 ...
    yichen大刀閱讀 7,787評論 0 4

友情鏈接更多精彩內(nèi)容