我来了我来了,今天介绍一下我接触过的Android 架构
首先一个应用为什么需要有架构?
先说俩句废话,这个世界上好多事情都是随机应变,学习更是这样的事情,做什么事情不能生搬硬套。
不要因为架构而架构,两三个页面没有必要架构。
MVP
Model 层 做数据的请求和处理。
Presenter 层做一些逻辑的处理。
View 层就是UI展示数据了。
MVP 是比较好的一个架构 首先层次分明,各司其职
这样做的好处,举个例子。
情景
领导分配给我一个模块,
1,第一个页面是一个列表。
2,第二个页面还是一个列表
3,第三个页面还是一个列表
功能
获取列表的数据
我一看很easy的需求啊,直接创建一个Activity ,然后咔咔咔一顿奋笔疾书,第一个页面搞定,调试完成,哈哈 复制三份,突然间我觉得像我这聪明的人太适合敲代码了。跟领导邀功去了。
领导看了看 笑了笑说功能实现了,但是不够优雅。
为什么这么说呢,假如一万个页面呢,复制一万遍吗,假如说后期需要修改一下怎么搞。
仔细一想,能当领导真不是白给的,很有道理啊 ,这必然是个很严重的问题。
因此需要把网络请求的所有逻辑都抽离出来封装好,形成一个模块,这个 模块只支持这个功能,一万个页面都直接调用他,如果要维护的话只需要维护这一个模块就好了。这样Model 可以重复使用。
情景二
产品上线,用户越来越多,我们不能老给用户看同一个数据啊,需要动态的加载啊,现在需要做一个分页功能。
干之前想想,经过之前的启发,把分页逻辑都放在Model中,不就行了,赶紧写,写完了又去找领导,领导一看,你这个还是很有进步的,没有把分页的逻辑放到每个页面当中,但是现在新的需求来了
有的页面加载一次加载一个页面,有的页面加载两个页面,有一万个页面就有一万种可能,你总不能在一个Model里边整一万个if和else去处理吧,如果放在Activity中又和页面逻辑藕合在一起了,所以现在需要一个中间层Presenter,P层负责从View层过来的数据经过加工传递给Model层,Model层网络请求的数据回来之后,传递给P层,经过逻辑处理,把数据处理完毕,直接传给View层。
V层也就是UI层,功能主要是数据展示和接受用户交互
来看张图
mvp.png
当用户点击了屏幕,事件从View层传到Presenter层,然后Presenter层把数据进行逻辑处理(分页+1 等等逻辑)交给ModelManager层,通过ModelManager找到对应功能的Model 去进行网络请求。(ModelManager 类似 ,通过一个Manager把所有的model 管理起来),当数据回来的时候,通过Presenter传到View中,View再去更新UI。
总结一下,
Model 层就是数据请求
Presenter层把数据逻辑处理好(排序,去重等等)
View层展示。
优点:解耦,代码结构清晰(单一原则各司其职)。
缺点:Presenter 持有View对象,可能造成内存泄漏,或者是网络请求回来View对象已经销毁了,造成空指针的问题。
MVVM
MVVM可以说是MVP的衍生物,为什么呢,因为早期开发没有明确的标准,给用户看到的效果都是一样的,没人管你一行代码实现还是一万行代码去实现一个功能,都是各个大佬免费分享的方案,大家相互借鉴(),但是现在goole官方出来说话了要统一风格,整理了一套方案,jetpack便捷化开发,MVVM就是这套工具下产生的东西,它最大的优点就是继承了MVP的优点,然后弥补了MVP的缺点,不会造成内村泄漏,回调的时候也不会发生崩溃,怎么实现的呢,拿好瓜子,听我胡说。
先看一张结构图
mvvm.pngView层和MVP的View层功能一样
ViewModel层和MVP的Presenter功能一样
Repository 和Model 是一样的功能。
因为事件流程逻辑都一样,所以这里不再重复,只说明内存泄漏和回调崩溃的问题。
第一个问题,内存泄漏和崩溃的根源
MVP之所以会内存泄漏,是因为Presenter中持有View对象的引用,这是根源,如果没有了View层的引用,就从根源杜绝了问题,不会有内存泄漏了。
第二个问题,没有View引用,我怎么把数据传到View层?
LiveData,很简单的东西却也是很神奇的东西上点代码看的更明白
mViewModel.getClassInfoData().observe(this, new Observer<ListBean<ClassInfoBean>>() {
@Override
public void onChanged(@Nullable ListBean<ClassInfoBean> classInfoBeanListBean) {
}
});
View层拿到ViewModel 的对象,拿到它里边的数据保存者LiveData(),然后通过观察者进行观察。
怎么才会触发onChanged方法呢
public void getClassInfoList(){
doGet(URLUtils.QUERY_CLASS_LIST, null, new XHttpCallBack<MyHttpResponse<ListBean<ClassInfoBean>>>() {
@Override
public void onSuccess(MyHttpResponse<ListBean<ClassInfoBean>> listBeanMyHttpResponse) {
getClassInfoData().postValue(listBeanMyHttpResponse.getData());
}
@Override
public void onError(Throwable error) {
super.onError(error);
getErrorData().setValue(new ErrorBean(XErrorUtils.ERROR.NETWORD_ERROR,"网络错误"));
}
});
}
post方法内部使用handler切换了主线程底层set一样的原理。
当我们在ViewModel中更新数据的时候,View那边自动回调onChanged方法了。
当另一边数据变化的时候,自动回调到onChanged方法,ViewModel层没有持有View对象中的任何引用的情况下更新了数据。
第三个问题,这样确实没有View引用,但是Activity销毁的时候,回调的时候会有崩溃问题啊?
看LiveData源码怎么规避掉的。
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
//这个方法看名字就知道是通知观察者 进行分发 数据的,继续往下看
}
.....
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
马赛克吸引一下
//这里是观察者观察的时候把所有观察者都存在了一个集合当中,现在遍历集合进行分发。
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
重点 considerNotify(iterator.next().getValue());// look 这里
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
.....
上边LiveData观察(注册)的时候需要两个参数,一个回调,另外一个是lifecycle相关,
简单说一下这是官方控制Activity证明周期的一种方案,现在不要你自己去控制了,官方大佬给方案了
你这样理解就好了,这样生命周期不符合的不进行回调(比如用户看不到的页面,这个需要了解lifecycle内容)
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
总结:LiveData所有观察者进行观察(注册)的时候,通过lifecycle对当前页面进行了生命周期监控,如果当前页面不符合要求,比如销毁等等就不会进行回调,从而优雅的避免了崩溃问题。(lifecycle怎么原理后续更新)
回到最初的问题,选择适合自己的架构,这个世界上最好的就是适合你的那个。
网友评论