概述
LiveData 是一个持有数据的类,它持有的数据是可以被观察者订阅的,当数据被修改时就会通知观察者。观察者可以是 Activity、Fragment、Service 等。
LiveData 能够感知观察者的生命周期,只有当观察者处于激活状态(STARTED、RESUMED)才会接收到数据更新的通知,在未激活时会自动解注册观察者,以减少内存泄漏。
使用 LiveData 保存数据时,由于数据和组件是分离的,当组件重建时可以保证数据不会丢失。
优点
确保 UI 界面始终和数据状态保持一致。
没有内存泄漏,观察者绑定到 Lifecycle 对象并在其相关生命周期 destroyed 后自行解除绑定。
不会因为 Activity 停止了而奔溃,如 Activity finish 了,它就不会收到任何 LiveData 事件了。
UI 组件只需观察相关数据,不需要停止或恢复观察,LiveData 会自动管理这些操作,因为 LiveData 可以感知生命周期状态的更改。
在生命周期从非激活状态变为激活状态,始终保持最新数据,如后台 Activity 在返回到前台后可以立即收到最新数据。
当配置发生更改(如屏幕旋转)而重建 Activity / Fragment,它会立即收到最新的可用数据。
LiveData 很适合用于组件(Activity / Fragment)之间的通信。
使用 添加相关依赖
LiveData 有两种使用方式,结合 ViewModel 使用以及直接继承 LiveData 类。
结合 ViewModel 使用
以下代码场景:点击按钮提示一个名字。
1 2 3 4 5 6 7 8 9 10 11 12 13 class MyViewModel : ViewModel () { private lateinit var name: MutableLiveData<String> fun getName () : MutableLiveData<String> { if (!::name.isInitialized) { name = MutableLiveData() } return name } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class LiveDataActivity : AppCompatActivity () { private lateinit var myViewModel: MyViewModel override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) setContentView(R.layout.activity_live_data) myViewModel = ViewModelProviders.of(this ).get (MyViewModel::class .java) myViewModel.getName().observe(this , Observer { Toast.makeText(baseContext, it, Toast.LENGTH_SHORT).show() }) btnSetName.setOnClickListener { myViewModel.getName().value = "张三" } } }
让数据(name)和组件(LiveDataActivity)分离,当 Activity 重建时,数据(name)不会丢失。
直接继承 LiveData 类
以下代码场景:在 Activity 中监听 Wifi 信号强度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 class WifiLiveData private constructor (context: Context) : LiveData<Int >() { private var mContext: WeakReference<Context> = WeakReference(context) companion object { private var instance: WifiLiveData? = null fun getInstance (context: Context ) : WifiLiveData { if (instance == null ) { instance = WifiLiveData(context) } return instance!! } } override fun onActive () { super .onActive() registerReceiver() } override fun onInactive () { super .onInactive() unregisterReceiver() } private fun registerReceiver () { val intentFilter = IntentFilter() intentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION) mContext.get ()!!.registerReceiver(mReceiver, intentFilter) } private fun unregisterReceiver () { mContext.get ()!!.unregisterReceiver(mReceiver) } private val mReceiver = object : BroadcastReceiver() { override fun onReceive (context: Context ?, intent: Intent ) { when (intent.action) { WifiManager.RSSI_CHANGED_ACTION -> getWifiLevel() } } } private fun getWifiLevel () { val wifiManager = mContext.get ()!!.applicationContext.getSystemService(android.content.Context.WIFI_SERVICE) as WifiManager val wifiInfo = wifiManager.connectionInfo val level = wifiInfo.rssi instance!!.value = level } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class LiveDataActivity : AppCompatActivity () { override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) setContentView(R.layout.activity_live_data) withExtendsLiveDataTest() } private fun withExtendsLiveDataTest () { WifiLiveData.getInstance(this ).observe(this , Observer { Log.e("LiveDataActivity" , it.toString()) }) } }
当组件(Activity)处于激活状态(onActive)时注册广播,处于非激活状态(onInactive)时注销广播。
源码解析 observe 注册流程 LiveData 通过 observe() 方法将被观察者 LifecycleOwner (Activity / Fragment) 和观察者 Observer 关联起来。
1 LiveData.observe(LifecycleOwner owner , Observer<T> observer)
进入 LiveData 的 observe() 方法中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public void observe (@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) { if (owner.getLifecycle().getCurrentState() == DESTROYED) { return ; } LifecycleBoundObserver wrapper = new LifecycleBoundObserver (owner, observer); ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper); if (existing != null && !existing.isAttachedTo(owner)) { throw new IllegalArgumentException ("Cannot add the same observer" + " with different lifecycles" ); } if (existing != null ) { return ; } owner.getLifecycle().addObserver(wrapper); }
从上面的代码可知,observe() 方法最终是会调用:
1 LifecycleOwner.getLifecycle().addObserver(LifecycleObserver)
因此 LiveData 是能够感知观察者的生命周期变化的。
感知生命周期变化 通过以上的分析,我们知道 LifecycleBoundObserver(LiveData 的内部类)是观察者,以下具体分析 LifecycleBoundObserver 的实现过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver { @NonNull final LifecycleOwner mOwner; LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) { super (observer); mOwner = owner; } @Override boolean shouldBeActive () { return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } @Override public void onStateChanged (LifecycleOwner source, Lifecycle.Event event) { if (mOwner.getLifecycle().getCurrentState() == DESTROYED) { removeObserver(mObserver); return ; } activeStateChanged(shouldBeActive()); } @Override boolean isAttachedTo (LifecycleOwner owner) { return mOwner == owner; } @Override void detachObserver () { mOwner.getLifecycle().removeObserver(this ); } }
当组件(Activity / Fragment)的生命周期发生改变时,onStateChanged() 方法将会被调用。若当前处于 DESTROYED 状态,则会移除观察者;若当前处于激活状态,则会调用 activeStateChanged() 方法。activeStateChanged() 方法位于父类 ObserverWrapper 中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 void activeStateChanged (boolean newActive) { if (newActive == mActive) { return ; } mActive = newActive; boolean wasInactive = LiveData.this .mActiveCount == 0 ; LiveData.this .mActiveCount += mActive ? 1 : -1 ; if (wasInactive && mActive) { onActive(); } if (LiveData.this .mActiveCount == 0 && !mActive) { onInactive(); } if (mActive) { dispatchingValue(this ); } }
再看看最终调用的 dispatchingValue() 方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 private void dispatchingValue (@Nullable ObserverWrapper initiator) { 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()); if (mDispatchInvalidated) { break ; } } } } while (mDispatchInvalidated); }
可以看到 dispatchingValue() 方法里面再通过 considerNotify() 方法将消息通知下去。
1 2 3 4 private void considerNotify (ObserverWrapper observer) { observer.mObserver.onChanged((T) mData); }
上面的 mObserver 正是我们调用 observe() 方法时传入的观察者。
总结上面的分析就是:调用 LiveData.observe(LifecycleOwner owner , Observer observer) 进行注册后,当 LiveData 数据发生变化后,最终就会调用 Observer 对象的 onChanged() 方法,并把变化的数据作为参数回传。
通知观察者更新数据的方式 LiveData 为我们提供了两种改变数据后,通知观察者更新数据的方式,一个是 setValue() 方法(必须在主线程调用 ),另一个是 postValue() 方法(必须在子线程调用 )。
setValue() 方法
1 2 3 4 5 6 7 @MainThread protected void setValue (T value) { assertMainThread("setValue" ); mVersion++; mData = value; dispatchingValue(null ); }
dispatchingValue() 方法会跑我们上面分析的流程,最终把改变的数据 value(对应上面的 mData)作为 onChanged() 方法的参数传给观察者。
postValue() 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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((T) newValue); } };
可以看出 postValue() 方法最终也会在主线程中调用 setValue() 方法。
文中 Demo GitHub 地址
参考资料:
Android开发——架构组件LiveData源码解析
Android Developers