LiveData简单解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: Android LiveData

啥是LiveData?

public abstract class LiveData {
    /***/
}复制代码

这个类就是LiveData 本文完!!!

hhh皮一下很开心

简单的介绍一下:

LiveData is a data holder class that can be observed within a given lifecycle.
官方类上面的介绍 简单的说就是可以 
在生命周期内感知到数据变化的一个东东 通过Lifecycle感知当前页面的生命周期 来决定是否要发送数据 
复制代码

如果你还不知道LiveData如何使用 那么建议看一下官方文档  


大召唤法:developer.android.com/topic/libra…

看完上面两个东西 我觉得应该会有两个疑问


1:怎么发送数据?

2:怎么感知生命周期?

ok 我们来一一解答:


question one:LiveData 是怎么做到发送数据的?

ok 用过的小伙伴都知道 使用setValue 和 postValue方法 那么 这两个方法做了啥?

一起来看看


SetValue

/**
 * Sets the value. If there are active observers, the value will be dispatched to them.
 * <p>
 * This method must be called from the main thread. If you need set a value from a background
 * thread, you can use {@link #postValue(Object)}
 *
 * @param value The new value
 */
@MainThread //注解1
protected void setValue(T value) {
    assertMainThread("setValue");//注解2
    mVersion++;
    mData = value;
    dispatchingValue(null);//注解3
}复制代码


注解1:MainThread  该注意代表着被标注的方法 和 类 只能在主线程中进行 如果在类上 整个类的方法都只能在主线程

注解2:assertMainThread  进行线程检查

注解1+注解2 = 我们知道了setValue 只能在主线程中运行  ///Nice 脑壳又进了一点知识复制代码


注解3:从名字看 是给我们观察者派发更新事件的 等下说


PostValue

既然setValue 只能在主线程发送 那么Android中的惯例 就有一个可以在异步线程分派事件的方法

so 决定就是你 皮卡丘(postValue)


/**
 * Posts a task to a main thread to set the given value. So if you have a following code
 * executed in the main thread:
 * <pre class="prettyprint">
 * liveData.postValue("a");
 * liveData.setValue("b");
 * </pre>
 * The value "b" would be set at first and later the main thread would override it with
 * the value "a".
 * <p>
 * If you called this method multiple times before a main thread executed a posted task, only
 * the last value would be dispatched.//如果你多次调用这个方法 那么只使用最后一个值
 *
 * @param value The new value
 */
protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);///注释1   
}
注释1:ArchTaskExecutor调用获取实例方法  然后将任务发送至主线程中/**
 * Returns an instance of the task executor.
 *
 * @return The singleton ArchTaskExecutor.
 */
@NonNull
public static ArchTaskExecutor getInstance() {///一个单利实例获取写法
    if (sInstance != null) {
        return sInstance;
    }
    synchronized (ArchTaskExecutor.class) {
        if (sInstance == null) {
            sInstance = new ArchTaskExecutor();
        }
    }
    return sInstance;
}
///私有构造
private ArchTaskExecutor() {
    mDefaultTaskExecutor = new DefaultTaskExecutor();
    mDelegate = mDefaultTaskExecutor;
}
@Override
public void postToMainThread(Runnable runnable) {
    mDelegate.postToMainThread(runnable);注解1
}复制代码



注解1:这个mDelegate 其实是上面私有构造器的DefaultTaskExecutor()的代理;所以它的postToMainThread方法的具体实现应该如下:

@Override
public void postToMainThread(Runnable runnable) {
    if (mMainHandler == null) {
        synchronized (mLock) { 
            if (mMainHandler == null) {
                mMainHandler = createAsync(Looper.getMainLooper());
            }
        }
    }
    //noinspection ConstantConditions
    mMainHandler.post(runnable);///看到MAinHandler 原来是这样跑到主线程去得
}复制代码


然后 就是问题来了 上面一系列的操作只是把任务切换到主线程运行  那任务呢?任务是啥?

ok 这个时候 我们在看LiveData.postValue 方法中 提交任务的那一块代码


ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);   
哈哈哈找到了 mPostValueRunnable 是你  那这个mPostValueRunnable是什么东西  跟着去看看复制代码
private final Runnable mPostValueRunnable = new Runnable() {
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        //noinspection unchecked
        setValue((T) newValue);///注释1
    }
};复制代码

注释1:好了 原来postValue只是切换线程后 最后还是调用setValue 方法


既然如此让我们再看看 刚刚的setValue中 还未说明的注释3吧

go dispatchingValue(null);//注解3
 @SuppressWarnings("WeakerAccess") /* synthetic access */
void dispatchingValue(@Nullable ObserverWrapper initiator) {
    if (mDispatchingValue) {///注解1:首先先判断是否是正在发送中
        mDispatchInvalidated = true;///是的话 return
        return;
    }
    mDispatchingValue = true;///标记为发送中
    ///一个do whild循环 :dowhile  至少执行一次
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {///判断该initiator  是否为空 setValue传进来的都是null
            considerNotify(initiator);///只更改当前ObserverWrapper 
            initiator = null;
        } else {
            ///否者分发所有地方
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;///取消标记为分发中的状态
}复制代码

从上面的代码 以及注释可以知道 正在改变数据的地方 是considerNotify 方法 gogogo 感觉要探宝成功了  


private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {///如果不是活越状态 就不继续发送事件   注解1
        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);
        //传入false  内部会进行判断是否需要再次判断是否执行onActive方法和onInactive方法回调。如果判断条件都满足会调用Observer的onChanged方法
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    //noinspection unchecked
    observer.mObserver.onChanged((T) mData);
    ///哦豁 实现了数据通知
}复制代码



Question two:如何实现感知生命周期?

我们通常在Fragment 或者 Activity中注册监听方法会这样写到

//数据监听
        viewModel.getLiveData().observe(getViewLifecycleOwner(), data-> {
            /***/
        }); 
复制代码

来看看observe做了啥


@MainThread ///主线程
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
    assertMainThread("observe");///标准检查线程
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {///如果是监听的生命周期是销毁状态
        // ignore ///忽略
        return;
    }
    ///创建一个与生命周期绑定的观察者
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);///这个方法做啥了  让我们看看注解1
    if (existing != null && !existing.isAttachedTo(owner)) {///如果existing   就是我们putIfAbsent 返回值 如果不为空 就说明已经绑定过了
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    owner.getLifecycle().addObserver(wrapper);///这个时候 就会真的添加进入观察
    Livedata就能够感知生命周期了
    }复制代码

注解1:putIfAbsent

* If the specified key is not already associated
 * with a value, associates it with the given value.
 *
 * @param key key with which the specified value is to be associated
 * @param v   value to be associated with the specified key
 * @return the previous value associated with the specified key,
 * or {@code null} if there was no mapping for the key
 */
public V putIfAbsent(@NonNull K key, @NonNull V v) {
    Entry<K, V> entry = get(key);///具体实现看下面get方法
    if (entry != null) {///如果当前节点不为空 就返回value
        return entry.mValue;
    }
    put(key, v);///否则存储 返回null
    return null;  
}
////get方法
protected Entry<K, V> get(K k) {
    Entry<K, V> currentNode = mStart;///Entry 是一个双向链表
    while (currentNode != null) {///一个whild 循环
        if (currentNode.mKey.equals(k)) {
            ///判断当前链表的k 是否和当前k相等  相等则跳出循环
            break;
        }
        currentNode = currentNode.mNext;///否则等于下个next 
    }
    return currentNode;///最后 如果当前链表中有k则返回当前节点  否则返回的是null 
}
复制代码



到此 两个问题 都解答完了啦

总结:

问题1:postValue  会把LiveData中已经定义好的 mPostValueRunnable  通过一个单利ArchTaskExecutor中postToMainThread方法 将任务提交给 DefaultTaskExecutor 发送至主线程执行runnable方法  而runnable中 会调用setValue  setValue会调用分派数据方法(dispatchingValue) 该方法中进行一系列检测  最终considerNotify啊 然后再检查是否满足发送条件 满足则发送

问题2:调用observe  检查生命周期状态是否是销毁的  不是销毁的话 创建一个与生命周期进行绑定的 观察者 LifecycleBoundObserver 然后再进行一系列检查是否满足条件 满足就执行

owner.getLifecycle().addObserver(wrapper);  添加观察


作者:FeanCheng

链接:https://juejin.cn/post/6844904088241455112

来源:掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

目录
相关文章
Livedata源码详细解析-面试这么讲就ok
Livedata源码详细解析-面试这么讲就ok
276 0
Livedata源码详细解析-面试这么讲就ok
|
2月前
|
监控 网络协议 Java
Tomcat源码解析】整体架构组成及核心组件
Tomcat,原名Catalina,是一款优雅轻盈的Web服务器,自4.x版本起扩展了JSP、EL等功能,超越了单纯的Servlet容器范畴。Servlet是Sun公司为Java编程Web应用制定的规范,Tomcat作为Servlet容器,负责构建Request与Response对象,并执行业务逻辑。
Tomcat源码解析】整体架构组成及核心组件
|
2月前
|
存储 NoSQL Redis
redis 6源码解析之 object
redis 6源码解析之 object
60 6
|
26天前
|
存储 缓存 Java
什么是线程池?从底层源码入手,深度解析线程池的工作原理
本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
什么是线程池?从底层源码入手,深度解析线程池的工作原理
|
1月前
|
开发工具
Flutter-AnimatedWidget组件源码解析
Flutter-AnimatedWidget组件源码解析
148 60
|
26天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
219 37
|
4天前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
35 9
|
18天前
|
编解码 开发工具 UED
QT Widgets模块源码解析与实践
【9月更文挑战第20天】Qt Widgets 模块是 Qt 开发中至关重要的部分,提供了丰富的 GUI 组件,如按钮、文本框等,并支持布局管理、事件处理和窗口管理。这些组件基于信号与槽机制,实现灵活交互。通过对源码的解析及实践应用,可深入了解其类结构、布局管理和事件处理机制,掌握创建复杂 UI 界面的方法,提升开发效率和用户体验。
89 12
|
2月前
|
测试技术 Python
python自动化测试中装饰器@ddt与@data源码深入解析
综上所述,使用 `@ddt`和 `@data`可以大大简化写作测试用例的过程,让我们能专注于测试逻辑的本身,而无需编写重复的测试方法。通过讲解了 `@ddt`和 `@data`源码的关键部分,我们可以更深入地理解其背后的工作原理。
36 1
|
2月前
|
开发者 Python
深入解析Python `httpx`源码,探索现代HTTP客户端的秘密!
深入解析Python `httpx`源码,探索现代HTTP客户端的秘密!
74 1

热门文章

最新文章

推荐镜像

更多