1. 程式人生 > 實用技巧 >Android 之 MVP 架構

Android 之 MVP 架構

MVP架構是為了讓各個模組之間降低耦合,方便維護,也可以讓程式碼更簡潔,讓程式碼簡潔的意思是讓程式碼更清晰,並不是讓程式碼更少;MVP契約者是為了進一步的低耦合、介面統一管理。

M(Model層) ——> 業務資料

V(View層)——> 檢視(activity,layout,自定義佈局)

P(Presenter層)——> Model 和 View 之間的互動

MVP架構優點

  • 降低耦合度,View層和Model層完全分離
  • 所有View層和Model層的互動都交給Presenter層
  • 後續擴充套件性和可維護性強

MVP架構缺點

  • 複雜的業務會導致presenter層過大
  • 通過UI事件的觸發對資料進行處理,activity 需要編寫大量的事件。通過事件呼叫 presenter 的業務處理方法,UI改變後牽扯的邏輯耦合度太高。
  • 如果 Presenter 過多地渲染了檢視,往往會使得它與特定的檢視的聯絡過於緊密,一旦檢視需要變更,那麼 Presenter 也需要變更了。

分包

  • base 包:基類
  • common包:存放一些常量,介面,公用的東西
  • contract包:契約者
  • model包:M層
  • presenter包:P層
  • ui包:V層
  • utils包:工具類
  • widget包:存放自定義的元件

Base 基類

放到 base 包裡

BaseActivity

/**
 * V層Activity的一個基類
 * @param <P>
 * @param <CONTRACT>
 */
public abstract class BaseActivity<P extends BasePresenter, CONTRACT> extends AppCompatActivity implements Contract<CONTRACT>, View.OnClickListener {

    //P層引用
    public P mPresenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(getContentViewId());

        initView();
        initData();
        initListener();

        mPresenter = getPresenterInstance();   //繫結P層
        mPresenter.bindView(this);
    }

    /**
     * 獲取佈局id
     * @return 返回佈局id
     */
    public abstract int getContentViewId();

    /**
     * 繫結元件
     */
    public abstract void initView();

    /**
     * 設定監聽器
     */
    public abstract void initListener();

    /**
     * 繫結資料
     */
    public abstract void initData();


    /**
     * 獲取P層例項
     */
    public abstract P getPresenterInstance();

    @Override
    protected void onDestroy() {
        super.onDestroy();
        destroy();
    }

    /**
     * activity 銷燬時執行的操作
     */
    public abstract void destroy();
}

BaseModel

/**
 * Model層的一個基類
 * @param <P>
 * @param <CONTRACT>
 */
public abstract class BaseModel<P extends BasePresenter, CONTRACT> implements Contract<CONTRACT> {

    /**
     * 關聯P層
     */
    public P mPresenter;

    /**
     * 繫結Presenter
     * @param mPresenter
     */
    public BaseModel(P mPresenter) {
        this.mPresenter = mPresenter;
    }
}

BasePresenter

/**
 * P層的一個基類
 * @param <V>
 * @param <M>
 * @param <CONTRACT>
 */
public abstract class BasePresenter<V extends BaseActivity, M extends BaseModel, CONTRACT> implements Contract<CONTRACT> {

    //V層引用
    public V mView;
    //M層引用
    public M mModel;

    /**
     * 繫結M層
     */
    public BasePresenter() {
        this.mModel = getModelInstance();
    }

    /**
     * 繫結V層
     * @param mView
     */
    public void bindView(V mView) {
        this.mView = mView;
    }

    /**
     * 解綁V層
     */
    public void unBindView() {
        this.mView = null;
    }

    /**
     * 獲取 M 層例項
     * @return
     */
    public abstract M getModelInstance();
}

Contract

/**
 * 獲取契約者的介面
 * @param <CONTRACT>
 */
public interface Contract<CONTRACT> {

    /**
     * 獲取契約者
     * @return
     */
    CONTRACT getContract();
}

契約

MVP的契約者(Contract)主要統一了介面管理,讓程式碼看起來更清晰。

舉例

/**
 * 登入契約介面
 */
public interface ILogin {

    /**
     * V層和P層介面
     */
    interface VP {
        void requestLoginContract(String name, String pwd);
        void responseLoginContract(boolean result);
    }

    /**
     * M層介面
     */
    interface M {
        void requestLoginContract(String name, String pwd) throws SQLException;
    }
}