Android項目實戰(1)搭建MVP框架

準備用MVP框架搭建一個自己的項目,之前的項目有用到過,但都是公司的同事搭建好的,現在自己搭建一個。
搭建之前先來了解一下MVP。
1、什麼是MVP

M(Model)負責數據的請求,解析,過濾等數據操作。
V(View)負責處理UI,通常以Activity Fragment的形式出現。
P(Presenter)View Model中間件,交互的橋樑。

2、MVP的優點

分離了UI邏輯和業務邏輯,降低了耦合。
Activity只處理UI相關操作,代碼變得更加簡潔。
UI邏輯和業務邏輯抽象到接口中,方便閱讀及維護。
把業務邏輯抽到Presenter中去,避免複雜業務邏輯造成的內存泄漏。

3、MVP與MVC的比較

MVP的優點:
1)複雜的邏輯處理放在presenter進行處理,減少了activity的臃腫。
2)M層與V層完全分離,修改V層不會影響M層,降低了耦合性。
3)可以將一個Presenter用於多個視圖,而不需要改變Presenter的邏輯。
3)P層與V層的交互是通過接口來進行的,便於單元測試。
MVP的缺點:
由於對視圖的渲染放在了Presenter中,所以視圖和Presenter的交互會過於頻繁,視圖需要改變,一般presenter也需要跟着改變.

/******************************************************************************************************************/

MVC的優點:
1):分工明確,各司所職。
2):一定程度上降低了代碼間的耦合性。
MVC的缺點:
1):隨着界面及其邏輯的複雜度不斷提升,Activity類的職責不斷增加,以致變得龐大臃腫。
2):視圖和控制器間過於緊密的聯繫,妨礙了各自的重用。

搭建過程
創建基類
在這裏插入圖片描述
1.對View進行封裝,主要處理顯示加載框、請求成功、請求失敗等操作

package com.lyw.modulemvp.base;
import android.content.Context;
/**
 * 功能描述:
 * Created on 2020/6/29.
 * @author lyw
 */

public interface IBaseView {

    /**
     * 顯示加載框
     */
    void showLoading();

    /**
     * 隱藏加載框
     */
    void dismissLoading();

    /**
     * 空數據
     *
     * @param tag TAG
     */
    void onEmpty(Object tag);

    /**
     * 錯誤數據
     *
     * @param tag      TAG
     * @param errorMsg 錯誤信息
     */
    void onError(Object tag, String errorMsg);

    /**
     * 上下文
     *
     * @return context
     */
    Context getContext();
}

2.對Presenter封裝 ,爲了避免持有View的Presenter做耗時操作而引起的內存泄漏,我們的Presenter應該和宿主Activity/Fragment同創建、同銷燬。

package com.lyw.modulemvp.base;

import android.content.Context;

import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 功能描述:
 * Created on 2020/6/29.
 * @author lyw
 */

public abstract class BasePresenter<M extends IBaseModel, V extends IBaseView> {

    private V mView;
    private M mModel;
    private WeakReference<V> weakReference;

    /**
     * 綁定View
     */
    @SuppressWarnings("unchecked")
    public void attachView(V view) {
        weakReference = new WeakReference<>(view);
        mView = (V) Proxy.newProxyInstance(
                view.getClass().getClassLoader(),
                view.getClass().getInterfaces(),
                new MvpViewHandler(weakReference.get()));
        if (this.mModel == null) {
            this.mModel = createModule();
        }
    }

    /**
     * 解綁View
     */
    public void detachView() {
        this.mModel = null;
        if (isViewAttached()) {
            weakReference.clear();
            weakReference = null;
        }
    }

    /**
     * 是否與View建立連接
     */
    protected boolean isViewAttached() {
        return weakReference != null && weakReference.get() != null;
    }

    protected V getView() {
        return mView;
    }

    protected M getModule() {
        return mModel;
    }

    protected Context getContext() {
        return getView().getContext();
    }

    protected void showLoading() {
        getView().showLoading();
    }

    protected void dismissLoading() {
        getView().dismissLoading();
    }


    /**
     * 通過該方法創建Module
     */
    protected abstract M createModule();

    /**
     * 初始化方法
     */
    public abstract void start();


    /**
     * View代理類  防止 頁面關閉P異步操作調用V 方法 空指針問題
     */
    private class MvpViewHandler implements InvocationHandler {

        private IBaseView mvpView;

        MvpViewHandler(IBaseView mvpView) {
            this.mvpView = mvpView;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //如果V層沒被銷燬, 執行V層的方法.
            if (isViewAttached()) {
                return method.invoke(mvpView, args);
            } //P層不需要關注V層的返回值
            return null;
        }
    }
}

3、對Activity的封裝,Fragment封裝同理,通過泛型規定Presenter,並且暴露抽象方法createPresenter()給子類來創建Presenter,基類實現BaseView中的公共方法,減少子類代碼的冗餘。

package com.lyw.modulemvp.base;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;

/**
 * 功能描述:Mvp Activity基類
 * Created on 2020/6/29.
 * @author lyw
 */
public abstract class BaseMvpActivity<P extends BasePresenter> extends BaseActivity implements IBaseView {
    protected P presenter;
    private Context mContext;
    @SuppressWarnings("unchecked")
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //創建present
        presenter = createPresenter();
        if (presenter != null) {
            presenter.attachView(this);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (presenter != null) {
            presenter.detachView();
            presenter = null;
        }
    }
    @Override
    public void showLoading() {
        if (mLoadingLayout != null) {
            mLoadingLayout.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public void dismissLoading() {
        if (mLoadingLayout != null) {
            mLoadingLayout.setVisibility(View.GONE);
        }
    }

    @Override
    public void onEmpty(Object tag) {

    }

    @Override
    public void onError(Object tag, String errorMsg) {

    }

    @Override
    public Context getContext() {
        return mContext;
    }
    /**
     * 創建Presenter
     */
    protected abstract P createPresenter();
}

子類的具體實現會在後面的demo完善,DEMO地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章