美文网首页
Android架构篇

Android架构篇

作者: 杨旭_ | 来源:发表于2019-10-08 21:11 被阅读0次

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

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

    相关文章

      网友评论

          本文标题:Android架构篇

          本文链接:https://www.haomeiwen.com/subject/usyipctx.html