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吧~
网友评论