MVP模式

305 阅读3分钟

简单的MVP, 写于2017年,传上来做个记录。 公司还是用的MVC,有好的MVP框架欢迎留言。

MVP模式

View 负责View的绘制以及与用户交互,是Activity(下图中的activity目录)

Model 是业务逻辑模型和实体模型,实际是一个接口(下图中的view目录)

Presenter 负责完成View于Model间的交互,(下图中的presenter目录)

封装原因:

1、BaseView(modle)

有很多类似方法,如获取数据,显示隐藏对话框,写一个公共的父类接口,这样不用每个model都写相同的接口。

2、BaseActivity(view) 1)实例化Presenter

2)onCreate时model绑定到presenter,onDestoty时解绑。这样不用每个Presenter都绑定和解绑model

3、BasePresenter (presenter) 提供绑定解绑View 的方法 一、Base 1、BaseView 定义所有视图通用的接口

public interface BaseView {
    /**显示进度框*/
    void showDialogProgress();
    /**隐藏进度框*/
    void dismissDialogProgress();
    /**加载数据*/
    void loadData();
    /**
*所有请求数据的地方都可以通用。
*/
    void loadDataOver(int type, Object object);
/** 显示失败信息 */
void loadDataError(Throwable e, int code);
}

2、BaseParenter 绑定View, Activity,onDestory时解绑

public abstract class BasePresenter<V extends BaseView> {
    protected V mView;
    private BaseActivity mActivityPresenter;
    //获取model实例
public void attach(V mView) {
        this.mView = mView;
    }
    //解绑model,activity onDestroy 时执行
    public void detach() {
        mView = null;
    }
    //获取Activity
    public void setActivity(BaseActivity mActivity) {
        this.mActivityPresenter = mActivity;
    }
    //解绑Activity,activity onDestroy 时执行
    public void deleteActivity() {
        mActivityPresenter = null;
    }
    protected Activity getActivity() {
        return mActivityPresenter;
    }
}

3、BaseActivity

public abstract class BaseActivity<V extends BaseView, T extends BasePresenter<V>> extends AppCompatActivity implements BaseView,BaseFragment.OnFragmentInteractionListener {
    protected String TAG = getClass().getSimpleName();
    protected T mPresenter;
    protected BaseActivity mActivity;
    protected ProgressDialog mDialogProgress;//进度对话框
    public static boolean isAlive = false;//是否存活
    public static boolean isRunning = false;//页面是否运行显示
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivity = BaseActivity.this;
        isAlive = true;
        setContentView(bindLayout());
        attachPresenter();
        loadData();
    }
    //将model绑定Presenter
    private void attachPresenter() {
        mPresenter = initPresenter();
        if (mPresenter != null) {
            mPresenter.attach((V) this);//presenter绑定view
            mPresenter.setActivity(mActivity);
        }
    }
    /**实例化presenter*/
    public abstract T initPresenter();
    /**[绑定布局] @return 布局id 必须执行 绑定布局*/
    @LayoutRes
    public abstract int bindLayout();
    @Override
    protected void onResume() {
        super.onResume();
        isRunning = true;
    }
    @Override
    protected void onPause() {
        super.onPause();
        isRunning = false;
    }
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        if (mPresenter != null) {
            mPresenter.detach();
            mPresenter.deleteActivity();
        }
        super.onDestroy();
        isAlive = false;
        isRunning = false;
        mPresenter = null;
    }
    @Override
    public boolean isRunning() {
        return isRunning;
    }
    @Override
    public boolean isAlive() {
        return isAlive && mActivity != null;// & ! isFinishing();导致finish,onDestroy内runUiThread不可用
    }
    @Override
    public void showDialogProgress() {
    }
    @Override
    public void dismissDialogProgress() {
    }
    protected final void runUiThread(Runnable action) {
        if (this.isFinishing()) {
            Log.w(TAG, "runUiThread  isAlive() == false >> return;");
            return;
        }
        runOnUiThread(action);
    }
    @Override
    public void onFragmentInteraction(Bundle bundle) {}
}
}

二、实现 1.MainView(model) 添加MainActivity要实现的方法。

public interface MainView extends BaseView{
    void onRequestSuccess();
}

2.MainParenter(parenter)

主要负责Activity的逻辑处理,处理完成后将结果通过接口mView 传递给Activity中, 通知Activity 的视图的改变。

public class MainPresenter extends BasePresenter<MainView> {
    int page;
    //模拟请求网络
    public void request() {
        mView.showDialogProgress();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        page++;
                        mView.dismissDialogProgress();
                        mView.loadDataOver(1, page);//这个要更新View 必须在UI线程执行。
                    	    mView.onRequestSuccess();
}
                });
            }
        }).start();
    }
}

3.MainActivity(view)

public class MainActivity extends BaseActivity<MainView, MainPresenter> implements MainView {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        findViewById(R.id.btn_load).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPresenter.request();
            }
        });
    }
    @Override
    public MainPresenter initPresenter() {
        return new MainPresenter();
    }
    @Override
    public int bindLayout() {
        return R.layout.activity_main;
    }
    @Override
    public void loadData() {
        mPresenter.request();
    }
    @Override
    public void loadDataOver(int type, Object object) {
        ((TextView) findViewById(R.id.tv_info)).setText("page " + 	Integer.parseInt(String.valueOf(object)));
    }
     @Override
     public void loadDataError(Throwable e, int code) {
    }
    @Override
    public void onRequestSuccess() {
        Toast.makeText(getApplicationContext(),"成功",Toast.LENGTH_SHORT).show();
    }
}