一个简单Mvp框架推荐

android中的各种框架

在主流的开发框架中,目前比较流行的框架有MVC,MVP,MVVM框架。

MVC

MVC框架算是比较常见的一种开发框架了,即模型-视图-控制器,model用来存储数据,view来做界面的显示与绘制,控制器用来处理逻辑,处理Model和View之间的交互,当然view和model之间还有交互,view可以直接从model类存取数据,model也能够直接改变view的显示。

###优点-缺点:
相较于没有框架来说,有了部分解耦,把业务逻辑和展示逻辑区分开,但是仍然耦合严重,在android中,一个activity几乎担任了view和control的职责,和model耦合很重。

MVP

在android中,mvp框架应该是目前用的较为广泛的,即模型-视图-Present,对于android来说,视图就是activity或者fragment及view,而present完全负责了view和model的逻辑交互。view只负责UI显示,present通过接口的形式,将处理完的逻辑调用接口改变UI。而model和view之间完全解耦,没有任何交互。

优点:

mvp相较于mvc来说,对于view和model是完全解耦了,model只负责自身的数据处理,所有的逻辑处理的放在了present,大大减少了android中view的逻辑处理。因为解耦,所以整个项目结构会比较清晰,也比较易于维护。

缺点

这个是解耦的设计的通病,一旦解耦了,代码量就上去了,而且文件数添加特别多,对于每一次改动,我们都需要改动inteface和inteface所对应的实现,但是为了项目的维护,这个应该是值得的。

MVVM

这个是最近几年刚提出的框架,通过xml和java代码的自动生成,来实现数据源与view的绑定与监听。一旦数据发生改变,view也会相应的作出改变。这个要了解的话可以看看我之前的一篇文章。

light-mvp框架的使用

这个框架是我在项目开发中写的,自己觉得挺方便的,所以分享一下。下面来看看这个mvp框架的简单使用。项目入口:https://github.com/xiejinlong/lightMvp

present

首先创建相应业务的present,内部定义了相应View需要实现的接口,prensent通过这个接口来改变UI

 public class ExamPresent extends BasePresent {
      public interface InterA {
        void change();
      }
      
      @BindV
      InterA interA;
      .....
  }

present需要添加@BindV注解,而且需要继承于BasePresent

activity or fragment

对于activity和fragment来说,实现绑定present的逻辑是一样的。

//activity
public class ExamActivity extends BaseActivity implement ExamPresent.InterA {
  
  ....
  @BindP
  ExamPresent present
  
  }

//fragment
public class ExamFragment extends BaseFragment implement ExamPresent.InterA {
  
  ....
  @BindP
  ExamPresent present
  
  }

对于activity来说,需要实现BaseActivity,而fragment需要实现BaseFragment,然后需要实现对应的present指定的接口,最后通过@BindP注解相应的present,一旦完成了这两步,view和present就绑定了
使用时,直接可以使用present.method()方式进行调用,无需再进行new实例和绑定解绑操作

生命周期

present生命周期随着fragment的oncreateView方法和activity的onCreate方法创建。 随着fragment的onDestoryView方法和activity的onDestory方法销毁。
一个fragment和acitivty支持绑定多个present, 一个present实例只支持绑定一个view

light-mvp实现原理

注解绑定V和P

先来看看两个注解的实现

//BindP
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindP {

}

//BindV
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindV {

}

这两个注解并没有参数,仅仅只是标识了变量的类型,以便于我们在反射中取值与赋值。
下面来看看activity绑定p的过程,fragment绑定p的过程基本类似。

 
 @SuppressWarnings("unchecked")
    public static void parasBindPresent(BaseMvpActivity activity) {
        Class clazz = activity.getClass();
	//遍历当前类以及其父类,看是否存在BindP注解
        while (!(clazz.equals(Object.class) )) {
            parasBindPresent(activity, clazz);
            clazz = clazz.getSuperclass();
        }
    }

   //绑定入口
    private static void parasBindPresent(BaseMvpActivity<BasePresent> activity, Class clazz) {
        //获取当前baseMvpActivity的成员变量,
	 Field[] fields = clazz.getDeclaredFields();
        for (Field f : fields) {
            //遍历所有的成员变量,找到添加了BindP注解的成员
            if (f.isAnnotationPresent(BindP.class)) {
                try {
		    //获取Present的类型
                    Class<?> c = f.getType();
	 	    //创建Present对象
                    Object t = c.newInstance();
                   
		    f.setAccessible(true);
		    //给activity中的present变量赋值为t,也就是我们刚创建出来的present对象
                    f.set(activity, t);
		    
		    //为了生命周期处理,需要对BasePresent和BaseMvpActivity互相引用
		    //所有的BasePresent定义了attachView方法,
                    ((BasePresent) t).attachView(activity);
		    //activity添加present
                    activity.addPresent((BasePresent) t);
		     //因为绑定是双向绑定,既然v已经绑定了p,那么接下来需要做的就是p绑定v
                    ParasBindVAnnotation.parasBindView(t, activity);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

上面的代码无非就是通过反射,进行v绑定p,下面看看p绑定v

public static void parasBindView(Object t, BaseMvpActivity activity) {
	//这个t就是上面创建出来present对象
        Field[] fields = t.getClass().getDeclaredFields();
        for (Field f : fields) {
	    //遍历所有方法,寻找添加了BindV注解的变量
            if (f.isAnnotationPresent(BindV.class)) {
                try {
		    //对present对象中添加了BindV注解的变量赋值
                    f.setAccessible(true);
                    f.set(t, activity);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

这样,一个p和v的绑定就完成了,当然这个只是两个对象的绑定。我们还需要看看两个Base类的实现,以及这个注解绑定何时调用,何时解绑。


public abstract class BaseMvpActivity<T extends BasePresent> extends GestureBaseActivity implements BaseView {

    private List<T> presentList = new CopyOnWriteArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ParasBindPAnnotation.parasBindPresent(this);

        for (T present : presentList) {
            if (present != null) {
                present.onCreate(savedInstanceState);
            }
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        for (T present : presentList) {
            if (present != null) {
                present.onStart();
            }
        }

    }

    @Override
    public void onResume() {
        super.onResume();
        for (T present : presentList) {
            if (present != null) {
                present.onResume();
            }
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        for (T present : presentList) {
            if (present != null) {
                present.onNewIntent(intent);
            }
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        for (T present : presentList) {
            if (present != null) {
                present.onSaveInstance(outState);
            }
        }
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        for (T present : presentList) {
            if (present != null) {
                present.onRestart();
            }
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        for (T present : presentList) {
            if (present != null) {
                present.onPause();
            }
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        for (T present : presentList) {
            if (present != null) {
                present.onStop();
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        for (T present : presentList) {
            if (present != null) {
                present.onDestroy();
                presentList.remove(present);
            }
        }
    }

    public void addPresent(T t) {
        if (t != null) {
            presentList.add(t);
        }
    }



    @Override
    public Context getCtx() {
        return this;
    }

    @Override
    public <T> LifecycleTransformer<T> bindUntilEve() {
        return bindUntilEvent(ActivityEvent.DESTROY);
    }
}

从这个BaseMvpActivity类中,我们能够知道,它内部维持了一个present列表,这就是为什么它能够同时绑定多个的原因。ParasBindPAnnotation.parasBindPresent调用是在activity的oncreate方法中调用,也就是activity在onCreate方法中进行的p和v的绑定,绑定的同时会将这个present添加到presentList中,然后在activity的生命周期中,都会回调present的相应的生命周期。然后在这个activity的onDestory中,也就是即将销毁时会进行解绑,调用present的onDestory方法,并从列表中移除。

public class BasePresent {

    protected BaseView mvpView;

    public BasePresent() {
    }

    public void attachView(BaseView mvpView) {
        this.mvpView = mvpView;
    }

    public void detach() {
        this.mvpView = null;
    }

    public void onCreate(Bundle saveInstanceState) {
    }

    public void onResume() {
    }

    public void onNewIntent(Intent intent) {
    }

    public void onPause() {
    }

    public void onStart() {
    }

    public void onStop() {
    }

    public void onDestroy() {
        detach();
        ParasBindVAnnotation.detachView(this);
    }


    public void onRestart() {
    }

    public void onSaveInstance(Bundle state) {
    }

    public void onRestoreSavedInstance(Bundle saveInstance) {
    }
}

在这个BasePresent中,我们可以先看到attachView这个方法,这个方法是在paraseBindPAnatation中调用的,这个BaseMvp是一些通用的mvp需要的方法,也就是在BaseMvp已经实现好了的。然后在ondestory方法中,首先会执行detach方法,将这个mvpView置为null,然后通过注解移除自身对activity或者fragment的引用。

public static void detachView(Object t) {
        Field[] fields = t.getClass().getDeclaredFields();
        for (Field f : fields) {
	    //对这个BindV的注解,做清空操作,即赋值为null
            if (f.isAnnotationPresent(BindV.class)) {
                try {
                    f.setAccessible(true);
                    f.set(t, null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

这样,整个mvp的绑定与解绑的流程就走完了。觉得还可以的就给个star吧~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值