Android架构篇

我来了我来了,今天介绍一下我接触过的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.png
View层和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怎么原理后续更新)

回到最初的问题,选择适合自己的架构,这个世界上最好的就是适合你的那个。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,333评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,812评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,016评论 0 246
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,293评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,650评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,788评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,003评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,741评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,462评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,681评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,168评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,528评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,169评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,119评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,902评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,846评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,719评论 2 274

推荐阅读更多精彩内容