Contents
  1. 项目GitHub地址:https://github.com/ms-liu/ProjectFrameDemo
  • 一、了解
  • 二、提升与改进(重点与目的)
    1. (一)框架分析
    2. (二)Code
    3. 实际代码请下载或者Frok项目。
    4. 项目GitHub地址:https://github.com/ms-liu/ProjectFrameDemo
    5. 个人邮箱:ms_liu163@163.com
  • 与孤独为伴,让自己来一场涅槃

    项目GitHub地址:https://github.com/ms-liu/ProjectFrameDemo

    一、了解

      在传统的Android项目开发过程中,按照MVC模块划分的话,往往会发现其实并不能很好的划分出各自的职责出来,Activity有时既需要扮演C的角色还需要扮演V的角色。这就导致Activity中代码耦合现象严重,尤其对于某些业务逻辑相对复杂的页面,动不动就是上千行的代码。
      可能对于这些页面一代开发人员来说还能很愉快的接受,但是当新人来维护时,这就会让他很头痛了;
      “他在写些什么? (黑人问号 黑人问号)他应该是个大神,代码我都看不懂,我要好好研究研究!”
      在这种现象的基础上,便有了MVP的开发模式:

    • Model:数据层——业务逻辑和实体类
    • View:视图层——页面展示
    • Presenter:逻辑层——数据和视图层交互

      单单从目前的分析来看,MVP和MVC并没有什么大的区别,当然这两者本身本质上的区别不大,都是用作解耦V和M,只是将MVC套到Android开发过程中的时候,让Activity等一些组件,角色扮演不是那么清晰,所以导致了问题产生。
      而在MVP的模式中,将Activity这些组件完全当成View层,让Activity职责单一化。Presenter负责数据处理,然后通过接口的形式达到与View交互的目的。让View和Model不在有交集。
    MVP结构
      这篇文章不作MVP如何编写的讲解,如需了解可自行百度,另外项目里面也包含了MVP 编写代码。

    二、提升与改进(重点与目的

      其实有过了解或者使用MVP的开发人员,应当都能体会感受到,MVP确实能够将Activity中代码简化。但是对于那些业务复杂界面,Presenter中代码也是会急剧增多,并且有时也会将View层中代码放到Presenter中,重新回到老状态。
      另外不知道有没有人碰到和我一样的问题,就是在使用MVP的过程中,有时在打开多个Activity页面后,回退过程中,在某些使用Fragment的Activity中会报出NullPointException,这是因为在我们打开过多页面时,由于内存和生命周期管理导致Fragment被系统回收,但是我们并没有将这些告知Presenter,从而发生NullPointException
      下面我们就一起来解决,这些问题。

    (一)框架分析

    MVPP结构
      在该框架中,我们在V和P之间加上了一个Proxy或Controller代理类,我们将会尽量少的让P和V直接进行交互接触,而是通过Proxy与V进行交互,在Proxy中预先处理部分逻辑,从而达到减轻Presenter职责的目的,让Presenter中代码更加简洁,更加专注于业务处理逻辑。

    (二)Code

    代码分包展示

    1、Model层

    • 定义IModel数据接口

      1
      2
      3
      4
      public interface IModel<T> {
      void setModel(T t);
      T getModel();
      }
    • 实现IModel接口

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      public class ImproveModelImpl implements IModel<ImproveInfoBean>{
      private ImproveInfoBean mModel;
      @Override
      public void setModel(ImproveInfoBean improveInfoBean) {
      this.mModel = improveInfoBean;
      }
      @Override
      public ImproveInfoBean getModel() {
      if (this.mModel == null){
      this.mModel = new ImproveInfoBean();
      }
      return mModel;
      }
      }

    2、View层代码

    • 定义View生命周期监听接口

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      public interface OnViewStateListener {
      void onCreate();
      void onPause();
      void onResume();
      void onStop();
      void onDestroy();
      }
    • 定义公共IView接口

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      public interface IView {
      // 绑定对View生命周期监听
      void bindListener(OnViewStateListener listener);
      Context getContext();
      // Toast提示
      void showToast(String message);
      //显示加载对话框
      void showLoadingDialog(String message);
      // 隐藏加载对话框
      void hideLoadingDialog();
      }
    • 编写ViewDelegate
      对 View操作的委托类,实现IView和OnViewStateListener接口中的方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      public class ViewDelegate implements IView,OnViewStateListener {
      private Context mCtx;
      private ProgressDialog mProgressDialog;
      public ViewDelegate(Context context){
      this.mCtx = context;
      }
      private List<OnViewStateListener> mOnViewStateListeners ;
      @Override
      public void bindListener(OnViewStateListener listener) {
      //用数组管理每一个View的生命周期,避免一个页面有多个监听
      if (mOnViewStateListeners == null){
      mOnViewStateListeners = new ArrayList<>();
      mOnViewStateListeners.add(listener);
      }else {
      if (!mOnViewStateListeners.contains(listener)){
      mOnViewStateListeners.add(listener);
      }
      }
      }
      @Override
      public Context getContext() {
      return mCtx;
      }
      @Override
      public void showToast(String message) {
      if (mCtx != null) {
      Toast.makeText(mCtx, message, Toast.LENGTH_SHORT).show();
      }
      }
      @Override
      public void showLoadingDialog(String message) {
      if (mCtx != null){
      mProgressDialog = new ProgressDialog(mCtx);
      }
      }
      @Override
      public void hideLoadingDialog() {
      if (mProgressDialog != null && mProgressDialog.isShowing()){
      mProgressDialog.hide();
      }
      }
      //------------------View生命周期管理--------------------------------------------------------
      @Override
      public void onCreate() {
      if (checkListener()){
      for (OnViewStateListener listener:
      mOnViewStateListeners) {
      listener.onCreate();
      }
      }
      }
      @Override
      public void onPause() {
      if (checkListener()){
      for (OnViewStateListener listener:
      mOnViewStateListeners) {
      listener.onPause();
      }
      }
      }
      @Override
      public void onResume() {
      if (checkListener()){
      for (OnViewStateListener listener:
      mOnViewStateListeners) {
      listener.onResume();
      }
      }
      }
      @Override
      public void onStop() {
      if (checkListener()){
      for (OnViewStateListener listener:
      mOnViewStateListeners) {
      listener.onStop();
      }
      }
      }
      @Override
      public void onDestroy() {
      if (checkListener()){
      for (OnViewStateListener listener:
      mOnViewStateListeners) {
      listener.onDestroy();
      }
      }
      }
      private boolean checkListener(){
      return mOnViewStateListeners != null && !mOnViewStateListeners.isEmpty();
      }
      }
    • 编写BaseActivity,在里面实现页面公共操作方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      public class BaseActivity extends AppCompatActivity implements IView{
      private ViewDelegate mDelegate;
      @Override
      protected void onCreate(@Nullable Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      //可以考虑注解创建
      mDelegate = new ViewDelegate(this);
      }
      @Override
      public void bindListener(OnViewStateListener listener) {
      mDelegate.bindListener(listener);
      }
      @Override
      public Context getContext() {
      return BaseActivity.this;
      }
      @Override
      public void showToast(String message) {
      mDelegate.showToast(message);
      }
      @Override
      public void showLoadingDialog(String message) {
      mDelegate.showLoadingDialog(message);
      }
      @Override
      public void hideLoadingDialog() {
      mDelegate.hideLoadingDialog();
      }
      }

    3、Presenter层代码

    • IPresenter公共接口,因为要监听View生命周期,让它继承OnViewStateListener 接口
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      public interface IImprovePresenter<M,V extends IView> extends OnViewStateListener {
      /**
      * View绑定
      * @param v
      */
      void bindView(V v);
      /**
      * 数据加载
      * @return
      */
      M loadModel();
      /**
      * View解绑
      */
      void detachView();
      }
    • 编写BasePresenter,实现部分共方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      public abstract class BaseImprovePresenter<M extends IModel,V extends IView> implements IImprovePresenter<M,V> {
      private List<String> mMethods;
      public BaseImprovePresenter(){
      this.mMethods = new ArrayList<>();
      }
      @Override
      public void onCreate() {
      }
      @Override
      public void onPause() {
      }
      @Override
      public void onResume() {
      }
      @Override
      public void onStop() {
      }
      @Override
      public void onDestroy() {
      }
      //---------------------模拟需要在生命周期中处理的逻辑--------------------------------------
      /**
      * 添加View生命周期结束时,需要结束的方法名称;
      * 类似RxJava中添加addSubscription()
      * @param methodName
      */
      public void addHandleMethod(String methodName){
      if (mMethods != null){
      mMethods.add(methodName);
      }
      }
      /**
      * 清楚
      * 类似RxJava中添加clearSubscription()
      */
      public void clearMethod(){
      if (mMethods != null && !mMethods.isEmpty()){
      mMethods.clear();
      }
      }
      }
    • 编写Presenter,

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      public class ImprovePresenter extends BaseImprovePresenter<ImproveModelImpl,IImproveView> {
      private IImproveView mView;
      private ImproveModelImpl mModel;
      @Override
      public void bindView(IImproveView iImproveView) {
      this.mView = iImproveView;
      mModel = loadModel();
      mView.showExplain(mModel.getModel().explain);
      }
      @Override
      public ImproveModelImpl loadModel() {
      addHandleMethod("异步请求数据方法");
      return new ImproveModelImpl();
      }
      @Override
      public void detachView() {
      clearMethod();
      }
      public void setInfo(String username, String password) {
      if (mModel != null){
      mModel.getModel().setName(username);
      mModel.getModel().setPassword(password);
      }
      }
      public void getInfoBean(){
      mView.showInfo("用户名:"+mModel.getModel().getName()+"\r\n密码:"+mModel.getModel().getPassword());
      }
      }
    • 编写PresenterProxy代理类

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      public class ImprovePresenterProxy implements IImprovePresenter<ImproveModelImpl,IImproveView>, View.OnClickListener {
      private ImprovePresenter mPresenter;
      private EditText etUserName;
      private EditText etPassword;
      private TextView componentShowInfo;
      private TextView componentExplain;
      private IImproveView mView;
      public ImprovePresenterProxy(ImprovePresenter improvePresenter){
      //判空
      checkPresenter(improvePresenter);
      //可以考虑依赖注入 方式
      this.mPresenter = improvePresenter;
      loadModel();
      }
      private void checkPresenter(ImprovePresenter improvePresenter) {
      if (improvePresenter == null){
      throw new NotBindPresenterException();
      }
      }
      @Override
      public ImproveModelImpl loadModel() {
      return mPresenter.loadModel();
      }
      @Override
      public void bindView(IImproveView iImproveView) {
      checkView(iImproveView);
      this.mView = iImproveView;
      mPresenter.bindView(iImproveView);
      }
      private void checkView(IImproveView iImproveView) {
      if (iImproveView == null){
      throw new NotBindViewException();
      }
      }
      @Override
      public void detachView() {
      mPresenter.detachView();
      }
      @Override
      public void onCreate() {
      //to do something
      }
      @Override
      public void onPause() {
      //to do something
      }
      @Override
      public void onResume() {
      //to do something
      }
      @Override
      public void onStop() {
      //to do something
      }
      @Override
      public void onDestroy() {
      detachView();
      }
      @Override
      public void onClick(View view) {
      int i = view.getId();
      if (i == R.id.btn_save) {
      if (etUserName != null && etPassword != null){
      mView.showToast("保存成功");
      mPresenter.setInfo(etUserName.getText().toString(),etPassword.getText().toString());
      }
      } else if (i == R.id.btn_get) {
      mPresenter.getInfoBean();
      } else {
      }
      }
      public void setComponentName(EditText etUsername) {
      this.etUserName = etUsername;
      }
      public void setComponentPassword(EditText etPassword) {
      this.etPassword = etPassword;
      }
      public void setComponentShowInfo(TextView componentShowInfo) {
      this.componentShowInfo = componentShowInfo;
      }
      public void setComponentExplain(TextView componentExplain) {
      this.componentExplain = componentExplain;
      }
      }

      至此,完成对MVP框架的完善和升级,完善后的MVP能够更好的用于实际生产,做到进一步的代码解耦的目的。并且由于加入了对View生命周期的管理,也很好的解决NullPointException问题。

    实际代码请下载或者Frok项目。

    项目GitHub地址:https://github.com/ms-liu/ProjectFrameDemo

    个人邮箱:ms_liu163@163.com

    Contents
    1. 1. 项目GitHub地址:https://github.com/ms-liu/ProjectFrameDemo
  • 一、了解
  • 二、提升与改进(重点与目的)
    1. 1. (一)框架分析
    2. 2. (二)Code
    3. 3. 实际代码请下载或者Frok项目。
    4. 4. 项目GitHub地址:https://github.com/ms-liu/ProjectFrameDemo
    5. 5. 个人邮箱:ms_liu163@163.com