Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 框架模式MVP在Android中的使用

框架模式MVP在Android中的使用

編輯:關於Android編程

前一篇文章中學習了MVC框架模式在Android中的使用,不了解什麼是MVC框架模式的親戳這裡 框架模式 MVC 在Android中的使用。其實谷歌Android開發團隊是鼓勵開發者利用MVC框架模式開發項目的,我們平時寫代碼也或多或少的在使用MVC框架模式開發項目,比如說谷歌自己退出來的Volley網絡請求框架就是遵循MVC框架的。我們可以理解為Volley框架是MVC當中的模型,也就是網絡數據處理這一塊,無需跟View視圖有任何關聯。也符合視圖和模型分離。可能你會覺得MVC框架已經很好用了,也能滿足任何項目開發,不錯,可是從上一篇博客你會發現,Controller控制器和View視圖顯示是在一個類Activity中體現出來的,而Android中Activity是擔當Controller控制器的角色的,如果界面操作方式繁瑣,視圖顯示復雜,那麼我們不得不在Activity中添加更多的View視圖顯示操作,這樣自然增加了Activity的代碼量,也導致了Activity承擔的任務和邏輯處理太多,職責不清晰。這一篇我們來介紹另外一種框架模式MVP。

MVP

MPV 是從經典的MVC模式演變過來的,其基本思路都是相通的。其中M是model模型,提供業務數據;P和MVC中的C擔當的角色相似,是Presenter控制者,進行邏輯處理。V是View視圖,顯示數據。MVP與MVC有著一個重大的區別:在MVP中View並不直接使用Model,它們之間的通信是通過Presenter (MVC中的Controller)來進行的,所有的交互都發生在Presenter內部,而在MVC中View會從直接Model中讀取數據而不是通過 Controller。

MVC框架圖MVC框架圖
這裡寫圖片描述MVP框架圖

從上面的框架圖可以看出MVC和MVP最大的區別就是 Model和View之間的關系。在MVC框架中,View是可以直接讀取Model模型中的數據的,Model模型數據發生改變是會通知View數據顯示發生相應的改變。而在MVP中Model和View之間的沒有任何聯系,是兩個完全獨立的模塊,當Model模型發生數據改變時,通過Presenter通知View視圖發生相應的UI改變。因此,個人覺得:MVP才是正真的視圖和模型完全分離,也就是Model模型進行業務數據處理和View視圖顯示沒有任何關聯。

MVP for Android

在Andorid項目中,我們習慣將Activity作為MVC中的控制者來達到Model模型和View視圖分離,但是在MVP框架模式中,通常將Activity作為View視圖層,因為在MVC框架模式中Activity和View視圖顯示關聯緊密,Activity中包含大量的View視圖顯示代碼,如果哪天老板說需要修改View視圖顯示,這時候你是不是感覺需要修改Activity中的大量代碼?這麼一來會將Activity中控制邏輯破壞,也導致Activity中承擔太多的職責。根據單一職責原則,Activity主要起到用戶交互作用,也就是接收用戶輸入,顯示請求結果。因此可以通過MVP框架模式來減輕Activity的職責。看看Android項目中怎麼實現吧!

同樣拿上一篇的天氣預報小項目來舉例子:

Model模型

和MVC框架模式一樣,Model模型處理數據代碼不變

/**
 * Created by xjp 2015-6-7
 * 天氣Model接口
 */
public interface WeatherModel {
    void loadWeather(String cityNO, OnWeatherListener listener);
}
.........

/**
 * Created by xjp on 2015/6/7.
 * 天氣Model實現
 */
public class WeatherModelImpl implements WeatherModel {
    @Override
    public void loadWeather(String cityNO, final OnWeatherListener listener) {
        /*數據層操作*/
        VolleyRequest.newInstance().newGsonRequest("http://www.weather.com.cn/data/sk/" + cityNO + ".html",
                Weather.class, new Response.Listener() {
                    @Override
                    public void onResponse(Weather weather) {
                        if (weather != null) {
                            listener.onSuccess(weather);
                        } else {
                            listener.onError();
                        }
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        listener.onError();
                    }
                });
    }
}

通過OnWeatherListener接口回調將Model模型處理的數據返回給Presenter控制者。

Presenter控制器

/**
 * Created by xjp on 2015/6/7.
 * 天氣 Presenter接口
 */
public interface WeatherPresenter {
    /**
     * 獲取天氣的邏輯
     */
    void getWeather(String cityNO);

}
..........


/**
 * Created by xjp on 2015/6/7.
 * 在Presenter層實現,給Model層回調,更改View層的狀態,確保Model層不直接操作View層
 */
public interface OnWeatherListener {
    /**
     * 成功時回調
     *
     * @param weather
     */
    void onSuccess(Weather weather);
    /**
     * 失敗時回調,簡單處理,沒做什麼
     */
    void onError();

}

.........

package org.rocko.demos.mvp.presenter.impl;

import org.rocko.demos.mvp.model.WeatherModel;
import org.rocko.demos.mvp.model.entity.Weather;
import org.rocko.demos.mvp.model.impl.WeatherModelImpl;
import org.rocko.demos.mvp.presenter.OnWeatherListener;
import org.rocko.demos.mvp.presenter.WeatherPresenter;
import org.rocko.demos.mvp.ui.view.WeatherView;

/**
 * Created by xjp on 2015/6/7.
 * 天氣 Presenter實現
 */
public class WeatherPresenterImpl implements WeatherPresenter, OnWeatherListener {
    /*Presenter作為中間層,持有View和Model的引用*/
    private WeatherView weatherView;
    private WeatherModel weatherModel;

    public WeatherPresenterImpl(WeatherView weatherView) {
        this.weatherView = weatherView;
        weatherModel = new WeatherModelImpl();
    }

    @Override
    public void getWeather(String cityNO) {
        weatherView.showLoading();
        weatherModel.loadWeather(cityNO, this);
    }

    @Override
    public void onSuccess(Weather weather) {
        weatherView.hideLoading();
        weatherView.setWeatherInfo(weather);
    }

    @Override
    public void onError() {
        weatherView.hideLoading();
        weatherView.showError();
    }
}

從代碼中我們可以看到Presenter控制器同時持有 WeatherModel和WeatherView對象且實現了OnWeatherListener接口取回Model模型數據,因此,WeatherPresenterImpl向WeatherModel發送數據請求,然後通過OnWeatherListener接口實現獲取請求結果,在將結果通過接口WeatherView把數據顯示到Activity擔當的View視圖中。從而達到徹底將Model和View完全分離,試想在這種情況下,如果你需要修改Model是完全不會影響View視圖代碼的修改的,同理,修改View視圖層的時候,也完全無需修改Model層。相當於Model和View互相不知道對方的存在,都是通過中間控制器Presenter來傳達通信。

View視圖

先定義一個View視圖顯示的接口WeatherView

/**
 * Created by xjp on 2015/6/7.
 */
public interface WeatherView {
    void showLoading();

    void hideLoading();

    void showError();

    void setWeatherInfo(Weather weather);
}

然後實現Activity實現WeatherView接口

/**
 * 天氣界面
 */
public class WeatherActivity extends BaseActivity implements WeatherView, View.OnClickListener {
    private Dialog loadingDialog;
    private EditText cityNOInput;
    private TextView city;
    private TextView cityNO;
    private TextView temp;
    private TextView wd;
    private TextView ws;
    private TextView sd;
    private TextView wse;
    private TextView time;
    private TextView njd;

    private WeatherPresenter weatherPresenter;

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

    }

    private void init() {
        cityNOInput = findView(R.id.et_city_no);
        city = findView(R.id.tv_city);
        cityNO = findView(R.id.tv_city_no);
        temp = findView(R.id.tv_temp);
        wd = findView(R.id.tv_WD);
        ws = findView(R.id.tv_WS);
        sd = findView(R.id.tv_SD);
        wse = findView(R.id.tv_WSE);
        time = findView(R.id.tv_time);
        njd = findView(R.id.tv_njd);

        findView(R.id.btn_go).setOnClickListener(this);

        weatherPresenter = new WeatherPresenterImpl(this); //傳入WeatherView
        loadingDialog = new ProgressDialog(this);
        loadingDialog.setTitle("加載天氣中...");
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_go:
                weatherPresenter.getWeather(cityNOInput.getText().toString().trim());
                break;
        }
    }


    @Override
    public void showLoading() {
        loadingDialog.show();
    }

    @Override
    public void hideLoading() {
        loadingDialog.dismiss();
    }

    @Override
    public void showError() {
        //Do something
        Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void setWeatherInfo(Weather weather) {
        WeatherInfo info = weather.getWeatherinfo();
        city.setText(info.getCity());
        cityNO.setText(info.getCityid());
        temp.setText(info.getTemp());
        wd.setText(info.getWD());
        ws.setText(info.getWS());
        sd.setText(info.getSD());
        wse.setText(info.getWS());
        time.setText(info.getTemp());
        njd.setText(info.getNjd());
    }

}

因此,Activity及從MVC中的Controller中解放出來了,這會Activity主要做顯示View的作用和用戶交互。每個Activity可以根據自己顯示View的不同實現View視圖接口WeatherView。

總結

MVP框架模式完全將Model模型和View視圖分離,從而使得代碼的耦合性第,利用MVP框架寫項目達到解耦作用。 MVP和MVC最大的區別是:MVC中的V可以從M中獲取數據,而MVP中M和V完全分離,互相不知道對方的存在,Presenter通過接口通信方式將V和M通信。 在Android中MVP框架 Activity擔當View視圖層和MVC框架模式不一樣Activity擔當控制器。

源碼地址下載:源碼地址

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved