Android Jetpack架构组件之LiveData

​​​​​​​

有时候,靠单纯的判断并不能确定成功的几率。与其在等待中浪费青春,不如在追求中燃烧生命。——《狼道》

目录
前言
一、简介
二、基本使用
三、源码分析
四、内容推荐
五、项目参考

前言

——这篇记录的是一个常用的Jetpack架构组件之一的LiveData。通俗讲它有两个显著作用:1.通过观察者模式当数据发生变化的时候通知UI更新。2.与生命周期绑定在一起,当组件生命周期发生变化处于激活时通知UI更新。这么说可能还有点不清晰,具体请看下文分解:

一、简介

官网文档 / Jetpack组件

(1)是什么

——LiveData是一个可观察的数据持有者类。与常规的可观察对象不同,LiveData是生命周期感知的,这意味着它尊重其他应用程序组件(如活动、片段或服务)的生命周期。这种意识确保LiveData只更新处于活动生命周期状态的应用程序组件观察者。

(2)有什么用

  1. 数据可以被观察者订阅

  2. 能够感知组件(Fragment、Activity、Service)的生命周期

  3. 只有在组件出于激活状态(STARTED、RESUMED)才会通知观察者有数据更新

(3)有什么优点

  1. 能够保证数据和UI统一

  2. 减少内存泄漏

  3. 当Activity停止时不会引起崩溃

  4. 不需要额外的手动处理来响应生命周期的变化

  5. 组件和数据相关的内容能实时更新

  6. 针对configuration change时,不需要额外的处理来保存数据

  7. 资源共享

​二、基本使用

(4)怎么使用

LiveData的使用方式有两种:1.使用LiveData对象;2.继承LiveData类

  • 使用LiveData对象

实现步骤:

1.创建一个LiveData实例来保存数据

2.创建Observer监听数据改变

3.设置值,如果有活动的观察者,值将被发送给他们

//创建一个定义onChanged()方法的观察者对象,该方法控制LiveData对象持有的数据更改时发生的情况。
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 1.创建一个LiveData实例来保存数据
        MutableLiveData<String> currentName = new MutableLiveData<String>();
        // 2.创建Observer监听数据改变
        final Observer<String> nameObserver = new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String newName) {
                //更新UI操作
                nameTextView.setText(newName);
            }
        };
        // 添加Observer
        currentName.observe(this, nameObserver);

    }

    public void onClick(View view){
        // 3.设置值 如果有活动的观察者 值将被发送给他们
        //主线程使用setValue
        model.getCurrentName().setValue("xxxx")
        //后台线程使用postValue
        //model.getCurrentName().postValue("xxxx")
    }
}
  • 继承LiveData类
//Demo1扩展LiveData类(监听网络状态)
public class NetworkLiveData extends LiveData<NetworkInfo> {

    private final Context mContext;
    static NetworkLiveData mNetworkLiveData;
    private NetworkReceiver mNetworkReceiver;
    private final IntentFilter mIntentFilter;

    private static final String TAG = "NetworkLiveData";

    public NetworkLiveData(Context context) {
        mContext = context.getApplicationContext();
        mNetworkReceiver = new NetworkReceiver();
        mIntentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
    }
    //单例
    public static NetworkLiveData getInstance(Context context) {
        if (mNetworkLiveData == null) {
            mNetworkLiveData = new NetworkLiveData(context);
        }
        return mNetworkLiveData;
    }

    @Override
    protected void onActive() {
        super.onActive();
        //当组件处于激活状态时注册广播
        mContext.registerReceiver(mNetworkReceiver, mIntentFilter);
    }

    @Override
    protected void onInactive() {
        super.onInactive();
         //当组件处于销毁状态时注销广播
        mContext.unregisterReceiver(mNetworkReceiver);
    }
    //监听网络状态
    private static class NetworkReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            ConnectivityManager manager = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
            getInstance(context).setValue(activeNetwork);
        }
    }
}

//使用过程
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        NetworkLiveData.getInstance(this).observe(this,new Observer(){
            @Override
            public void onChanged(@Nullable final String newName) {
                // Update UI
            }
        })
    }
}

LiveData的使用方式相对比较简单。实现方式也比较容易。就不描述太多细节。相信大家看代码会比看解释更容易理解。

三、源码分析

——因为LiveData是抽象类,所以我们要使用它就需要写一个类来继承LiveData。
——当然系统也帮我们写了几个可直接使用的类,MutableLiveData,MediatorLiveData。

1.MutableLiveData源码

// 创建了一个MutableLiveData实例
MutableLiveData<String> liveData = new MutableLiveData<>();
// MutableLiveData源码
public class MutableLiveData<T> extends LiveData<T> {
      @Override
      public void postValue(T value) {
         super.postValue(value);
      }
      @Override
      public void setValue(T value) {
            super.setValue(value);
      }
}

——MutableLiveData把LiveData的postValue方法与setValue接口暴露出来可供调用。这个后面使用的时候在分析

2.LiveData的observe源码

//创建Observer监听数据改变
liveData.observe(this, new Observer<String>() {
    @Override
    public void onChanged(String s) {
        binding.setName(s);
    }
});

(1)observe源码

        //该方法主要把observer与Activity(组件)的生命周期绑定在一起。当Activity(组件)状态改变的时候通知observer
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //请看(5) 
        assertMainThread("observe");
        //当前Activity(组件)状态处于销毁状态时 是则返回 
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //请看(2) 
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //以键值对的形式存储observer于LifecycleBoundObserver,如果LifecycleBoundObserver已经存储过则ObserverWrapper返回空 
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //判断是否是同一个LifecycleOwner 
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        //这里拦截已经添加过的LifecycleBoundObserver
        if (existing != null) {
            return;
        }
        //添加一个wrapper,它将在LifecycleOwner状态更改时得到通知 具体原理可以看楼主Lifecycle原理篇
        owner.getLifecycle().addObserver(wrapper);
    }

(2)LiveData的内部类LifecycleBoundObserver源码

        //该类通过实现GenericLifecycleObserver监听生命周期变化更新Observer传递的数据
    //继承ObserverWrapper根据Activity(组件)的生命周期管理着Observer
    class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @NonNull
        final LifecycleOwner mOwner;
        //observer传给ObserverWrapper的构造函数
        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }
        //返回当前Activity(组件)的生命状态是否是STARTED或者RESUMED
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
        //通过实现GenericLifecycleObserver接口的onStateChanged方法监听Activity(组件)生命周期变化
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            //判断Activity(组件)生命周期状态是否是DESTROYED  是则移除观察者
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                //请看(4)
                removeObserver(mObserver);
                return;
            }
            //Activity(组件)生命周期改变 通知ObserverWrapper
            activeStateChanged(shouldBeActive());
        }
        //重写ObserverWrapper的isAttachedTo方法判断是不是同一个生命周期
        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }
        //重写ObserverWrapper的detachObserver方法移除LifecycleBoundObserver
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

(3)LiveData的内部抽象类ObserverWrapper源码

        // 封装Observer的一些属性与方法
    private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;
        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }
        abstract boolean shouldBeActive();
        //判断是否是同一个生命周期
        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }
        void detachObserver() {}        
        // 设置ObserverWrapper的mActive状态与添加mActiveCount数量 
        void activeStateChanged(boolean newActive) {
            //判断Activity(组件)状态是否改变 有没则返回
            if (newActive == mActive) {
                return;
            }
            //设置mActive状态
            mActive = newActive;
            //判断当前观察者数量是否为0
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            //当Activity(组件)是激活状态时+1 反之-1
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            //当Activity(组件)状态属于激活并wasInactive为ture时调用onActive() 
            if (wasInactive && mActive) {
                //也就是当观察者的数量从0变为1时调用
                onActive();
            }
            //当活动观察者的数量从1变为0时调用
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            // 当Activity(组件)属于激活是调用dispatchingValue
            if (mActive) {
                //查看(6)分析
                dispatchingValue(this);
            }
        }
    }

(4)LiveData类的removeObserver方法

        //从观察者列表中删除给定的观察者
    @MainThread
    public void removeObserver(@NonNull final Observer<? super T> observer) {
        //请看(5) 
        assertMainThread("removeObserver");
        //从mObservers列表中移除observer
        ObserverWrapper removed = mObservers.remove(observer);
        if (removed == null) {
            return;
        }
        //移除Observer并通知相关属性记录更改
        removed.detachObserver();
        removed.activeStateChanged(false);
    }

(5)LiveData类的assertMainThread方法

        //用于判断是否在主线程  不是则抛出异常IllegalStateException
    private static void assertMainThread(String methodName) {
        if (!ArchTaskExecutor.getInstance().isMainThread()) {
            throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                    + " thread");
        }
    }

(6)LiveData类的dispatchingValue方法分析

        // 经过一系列的判断 最后调用considerNotify方法更新数据
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        //判断值是否在分发当中    
            if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                //请看(7) 
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    //请看(7) 
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
            mDispatchingValue = false;
        }
        }

(7)LiveData类的considerNotify方法分析

        //当Activity(组件)属于激活状态时 把数据传给observer的onChanged方法
    private void considerNotify(ObserverWrapper observer) {
        // Activity(组件)状态属于非激活状态时 返回
        if (!observer.mActive) {
            return;
        }
        // 继续检测observer属于非激活状态时设置activeStateChanged为false 并返回
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        // 用于拦截数据没更新,当调用setValue时mVersion会加1,也就是没有新数据时在这里会被拦截 不会调用到mObserver.onChanged方法
        if (observer.mLastVersion > = mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //把数据传给observer的onChanged方法
        observer.mObserver.onChanged((T) mData);
    }

总结:

  • 通过liveData.observe()方法首先判断组件若处于激活状态,创建绑定生命周期与观察者的关键类。

  • 判断该类是否存储过,若存储过则抛出异常。

  • 将绑定类添加到lifecycle生命周期中,监听组件生命周期变化。(具体实现方式看Lifecycle原理)

  • 当生命周期发生变化时调用观察者的onChange()方法 ,把值传递过去。中间经过一系列判断,具体看源码。

3.设置值setValue源码

        //通过解析1的MutableLiveData源码可知最后调用的是LiveData的setValue与postValue
    //设置值。如果有活动的观察者,值将被发送给他们
    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        //请看(6)
        dispatchingValue(null);
    }
    //非主线程设置值
    protected void postValue(T value) {
        boolean postTask;
        //同步代码块 
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        //检测上一个任务是否执行完毕
        if (!postTask) {
            return;
        }
        //将任务发送到主线程以设置给定的值
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }   

    private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //最后也是通过setValue方法进行通知
            setValue((T) newValue);
        }
    };

总结:

  • postValue方法主要是将任务切换到主线程并调用了setValue方通知观察者。
  • 而setValue方法则是调用了dispatchingValue()将值分发给Observer.onChanged方法。

四、内容推荐

五、项目参考

本文相关代码及Demo都放在下面项目中。有兴趣可体验一把

Github / apk下载体验地址

若您发现文章中存在错误或不足的地方,希望您能指出!

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

推荐阅读更多精彩内容

  • Android Jetpack介绍 Android Jetpack 是一套组件、工具和指导,可以帮助您快速构建出色...
    jiantaocd阅读 23,558评论 6 54
  • 最是人间留不住,朱颜辞镜花辞树——王维 最是人间留不住,朱颜辞镜花辞树——王维 曾经有一个人对我说:别对我抱太大希...
    碧海飞鸿2016阅读 207评论 0 1
  • Day 6: 1. 开头不要重读(不是看声音大小,保持一声);尝试给自己做一下心理暗示,不要头重脚轻,虎头蛇尾地去...
    蓬蓬豆的小马甲呀阅读 153评论 0 0
  • 朕已阅 这书也看了挺久了,不过看完也没什么感觉。去豆瓣上看了看书评,挺多人骂作者,好奇怪。现在的人写书都大不如前人...
    青木729阅读 181评论 0 0
  • 盯着手机屏幕几十秒,心中明明有千万惆怅,却发现自己不知道该写些什么。 感觉很糟糕,非常糟糕,而且一切好像都在变得更...
    吴聊_Vicki阅读 190评论 0 1