文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android源码进阶之LiveData工作原理详解

2024-12-14 00:53

关注

前言

LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。

这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

LiveData本身是观察者,观察组件的Lifecycle,也是被观察者,数据变化时要通知数据的观察者。

前面我们讲解了Lifecycle实现原理,今天我们来看LiveData

源码进阶之lifecycle组件原理分析

一、livedata的在app中的应用

1、使用livedata的步骤

2、livedata的简单例子

在viewModel中之定义live data

  1. public class NameViewModel extends ViewModel { 
  2. // Create a LiveData with a String 
  3. private MutableLiveData mCurrentName; 
  4.     public MutableLiveData getCurrentName() { 
  5.         if (mCurrentName == null) { 
  6.             mCurrentName = new MutableLiveData(); 
  7.         } 
  8.         return mCurrentName; 
  9.     } 
  10. // Rest of the ViewModel... 

在activity或者Fragment中实施监听来更新ui

  1. public class NameActivity extends AppCompatActivity { 
  2.     private NameViewModel mModel; 
  3.     @Override 
  4.     protected void onCreate(Bundle savedInstanceState) { 
  5.         super.onCreate(savedInstanceState); 
  6.         // Other code to setup the activity... 
  7.         // Get the ViewModel. 
  8.         mModel = ViewModelProviders.of(this).get(NameViewModel.class); 
  9.         // Create the observer which updates the UI. 
  10.         final Observer nameObserver = new Observer() { 
  11.             @Override 
  12.             public void onChanged(@Nullable final String newName) { 
  13.                 // Update the UI, in this case, a TextView. 
  14.                 mNameTextView.setText(newName);    
  15.                  //注意这里 在MVVM 中不是这样写的 这里只是单行绑定 
  16.             } 
  17.         }; 
  18.         // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer. 
  19.         mModel.getCurrentName().observe(this, nameObserver);      
  20.         //注意这个地方用没有用Java8的lambda表达式,可以写的更加简练, 
  21.     } 

更新livedata对象

调用setValue(T)示例会导致观察者onChanged()使用该值调用其ui进行刷新。该示例示出了按钮按下,但setValue()还是postValue()可以被调用以更新mName为各种各样的原因,包括响应于网络请求或数据库负荷完成; 在所有情况下,呼叫setValue()或postValue()触发观察员并更新UI;

  1. mButton.setOnClickListener(new OnClickListener() { 
  2.     @Override 
  3.     public void onClick(View v) { 
  4.         String anotherName = "John Doe"
  5.         mModel.getCurrentName().setValue(anotherName); 
  6.     } 
  7. }); 
  8. mButton.setOnClickListener(new OnClickListener() { 
  9.     @Override 
  10.     public void onClick(View v) { 
  11.         String anotherName = "John Doe"
  12.         mModel.getCurrentName().setValue(anotherName); 
  13.     } 
  14. }); 

二、livedata原理详细分析

1、observe 方法

  1. //map 的 key 为LiveData数据观察者,value为组件的Lifecycle观察者 
  2.     private SafeIterableMap, ObserverWrapper> mObservers = 
  3.             new SafeIterableMap<>(); 
  4.     @MainThread 
  5.     public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) { 
  6.         assertMainThread("observe"); 
  7.         //判断当前生命周期的状态 
  8.         if (owner.getLifecycle().getCurrentState() == DESTROYED) { 
  9.             // ignore 
  10.             return
  11.         } 
  12.         //Lifecycle的生命周期变化逻辑在这里 
  13.         LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); 
  14.         //mObservers 保存 
  15.         ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper); 
  16.         if (existing != null && !existing.isAttachedTo(owner)) { 
  17.             throw new IllegalArgumentException("Cannot add the same observer" 
  18.                     + " with different lifecycles"); 
  19.         } 
  20.         if (existing != null) { 
  21.             return
  22.         } 
  23.         //感知lifecycle的生命周期变化 
  24.         owner.getLifecycle().addObserver(wrapper); 
  25.     } 

2、LifecycleBoundObserver

  1. class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver { 
  2.         @NonNull 
  3.         //一般组件,比如Activity、fragment可以会实现LifecycleOwner ,可以拿到lifecycle 
  4.         final LifecycleOwner mOwner; 
  5.         LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer observer) { 
  6.             super(observer); 
  7.             mOwner = owner; 
  8.         } 
  9.          
  10.         @Override 
  11.         boolean shouldBeActive() { 
  12.             return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); 
  13.         } 
  14.         @Override 
  15.         public void onStateChanged(@NonNull LifecycleOwner source, 
  16.                 @NonNull Lifecycle.Event event) { 
  17.             //获取当前生命周期状态 
  18.             Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState(); 
  19.             //如果组件已销毁了,就移除观察 
  20.             if (currentState == DESTROYED) { 
  21.                 removeObserver(mObserver); 
  22.                 return
  23.             } 
  24.             Lifecycle.State prevState = null
  25.             while (prevState != currentState) { 
  26.                 prevState = currentState; 
  27.                 activeStateChanged(shouldBeActive()); 
  28.                 currentState = mOwner.getLifecycle().getCurrentState(); 
  29.             } 
  30.         } 
  31.          
  32.         @Override 
  33.         boolean isAttachedTo(LifecycleOwner owner) { 
  34.             return mOwner == owner; 
  35.         } 
  36.          
  37.         @Override 
  38.         void detachObserver() { 
  39.             mOwner.getLifecycle().removeObserver(this); 
  40.         } 
  41.     } 

3、activeStateChanged

ObserverWrapper 这个类里面有个方法,后面的粘性事件会用到;

  1. void activeStateChanged(boolean newActive) { 
  2.             //组件状态如果不变返回 
  3.             if (newActive == mActive) { 
  4.                 return
  5.             } 
  6.             // immediately set active state, so we'd never dispatch anything to inactive 
  7.             // owner 
  8.             mActive = newActive; 
  9.             changeActiveCounter(mActive ? 1 : -1); 
  10.             //如果是活动的就发送数据 
  11.             if (mActive) { 
  12.                 dispatchingValue(this); 
  13.             } 
  14.         } 

4、发送数据分析

4.1、postValue 发送数据到主线程

这个方法最核心的就是利用主线程Handler发送数据,一步步拆开分析;

  1. protected void postValue(T value) { 
  2.         boolean postTask; 
  3.         //加锁 
  4.         synchronized (mDataLock) { 
  5.             postTask = mPendingData == NOT_SET; 
  6.             //保存要发送的数据value 
  7.             mPendingData = value; 
  8.         } 
  9.         if (!postTask) { 
  10.             return
  11.         } 
  12.         //利用主线程Handler发送 
  13.         ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable); 
  14.     } 

4.2、postValue 其实就是 setValue

在postValue 要发送的 Runnable ,可以看到最后一行就是 setValue 方法,数据也即是之前保存的mPendingData ,只是在这又给 newValue;

  1. private final Runnable mPostValueRunnable = new Runnable() { 
  2.         @SuppressWarnings("unchecked"
  3.         @Override 
  4.         public void run() { 
  5.             Object newValue; 
  6.             synchronized (mDataLock) { 
  7.                 newValue = mPendingData; 
  8.                 mPendingData = NOT_SET; 
  9.             } 
  10.             setValue((T) newValue); 
  11.         } 
  12.     }; 

4.3、postToMainThread 主线程Handler

ArchTaskExecutor 类 postToMainThread 方法,实际就是 DefaultTaskExecutor 类执行 postToMainThread 方法;

  1. public class ArchTaskExecutor extends TaskExecutor { 
  2.     @NonNull 
  3.     private TaskExecutor mDelegate; 
  4.     @NonNull 
  5.     private TaskExecutor mDefaultTaskExecutor; 
  6.     private ArchTaskExecutor() { 
  7.         mDefaultTaskExecutor = new DefaultTaskExecutor(); 
  8.         mDelegate = mDefaultTaskExecutor; 
  9.     } 
  10.     ... 
  11.     @Override 
  12.     public void postToMainThread(Runnable runnable) { 
  13.         mDelegate.postToMainThread(runnable); 
  14.     } 
  15.     ... 

4.4、DefaultTaskExecutor类

我们知道是 DefaultTaskExecutor. postToMainThread,就直接看这个方法,哎呀,太熟悉的代码,创建 Handler ,传入的是 Looper.getMainLooper() ,就是主线程Handler ,然后就 post 消息;

  1. public class DefaultTaskExecutor extends TaskExecutor { 
  2.     @Nullable 
  3.     private volatile Handler mMainHandler; 
  4.     @Override 
  5.     public void postToMainThread(Runnable runnable) { 
  6.         if (mMainHandler == null) { 
  7.             synchronized (mLock) { 
  8.                 if (mMainHandler == null) { 
  9.                     mMainHandler = createAsync(Looper.getMainLooper()); 
  10.                 } 
  11.             } 
  12.         } 
  13.         //noinspection ConstantConditions 
  14.         mMainHandler.post(runnable); 
  15.     } 

4.5、setValue 方法

mVersion 在初始化的构造方法里就赋值了,为-1,每次setValue,版本号就会变一次;

setValue 也就是用 mData 保存一下 value ,然后交给 dispatchingValue 方法处理;

  1. @MainThread 
  2.     protected void setValue(T value) { 
  3.         assertMainThread("setValue"); 
  4.         mVersion++; 
  5.         mData = value; 
  6.         dispatchingValue(null); 
  7.     } 

6、dispatchingValue 方法

setValue走该方法,传的 initiator为空,那就遍历 mObservers 保存的观察者发送数据;

  1. @SuppressWarnings("WeakerAccess")  
  2.     void dispatchingValue(@Nullable ObserverWrapper initiator) { 
  3.         if (mDispatchingValue) { 
  4.             mDispatchInvalidated = true
  5.             return
  6.         } 
  7.         mDispatchingValue = true
  8.         do { 
  9.             mDispatchInvalidated = false
  10.             if (initiator != null) { 
  11.                 //粘性事件,就单个观察者接受数据 
  12.                 considerNotify(initiator); 
  13.                 initiator = null
  14.             } else { 
  15.                 //setvalue 传过来 initiator 为空,执行这里 
  16.                 // mObservers 拿出来,逐个发送数据 
  17.                 for (Iterator, ObserverWrapper>> iterator = 
  18.                         mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { 
  19.                     considerNotify(iterator.next().getValue()); 
  20.                     if (mDispatchInvalidated) { 
  21.                         break; 
  22.                     } 
  23.                 } 
  24.             } 
  25.         } while (mDispatchInvalidated); 
  26.         mDispatchingValue = false
  27.     } 

4.7、considerNotify 判断发送数据

  1. private void considerNotify(ObserverWrapper observer) { 
  2.         //组件是否活动 
  3.         if (!observer.mActive) { 
  4.             return
  5.         } 
  6.         // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet. 
  7.         // 
  8.         // we still first check observer.active to keep it as the entrance for events. So even if 
  9.         // the observer moved to an active state, if we've not received that event, we better not 
  10.         // notify for a more predictable notification order
  11.         //判断粘性事件 
  12.         if (!observer.shouldBeActive()) { 
  13.             observer.activeStateChanged(false); 
  14.             return
  15.         } 
  16.         //校验是否发送过数据 
  17.         if (observer.mLastVersion >= mVersion) { 
  18.             return
  19.         } 
  20.         observer.mLastVersion = mVersion; 
  21.         //发送数据 
  22.         observer.mObserver.onChanged((T) mData); 
  23.     } 

5、粘性事件分析

总结:

1、LifecycleOwner生命周期从非活跃变成活跃状态时:

Livedata添加一个观察者时,会关联一个LifecycleOwner,然后把这个观察者包装成一个LifecycleBoundObserver,和LifecycleOwner的getLifecycle关联,当LifecycleBoundObserver的生命周期变化时,会调用LifecycleBoundObserver的onStateChanged方法,在这个方法中判断当前生命周期和上次的生命周期是否是同一类型(要么活跃要么非活跃),如果是,就直接返回,避免重复通知(start通知了,resume就不需要通知了),如果不是同一类型,并且当前生命周期是活跃状态,就调用dispatchingValue方法通知观察者,判断LifecycleOwner是否时活跃状态,如果是,将Livedata中持有的最新更新给观察者;

2、Livedata中的值改变时:

 

同样是调用dispatchingValue,判断LifecycleOwner是否时活跃状态,如果是,就遍历通知所有观察者;

 

来源: Android开发编程内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯