LiveData的使用及原理
-
- 1.LiveData的使用
- 2.原理
- 3.自定義LiveData
LiveData是一個 可觀察的資料持有類,它與常見的可觀察對象不同的是它有生命周期意識,即它能夠感覺元件,如activities, fragments, services等的生命周期變化。以前我們可會用EventBus來做事件傳遞,現在用LiveData也是不錯。
1.LiveData的使用
- 使用添加依賴項grale.build(:app)
dependencies {
...
def lifecycle_version = "2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
}
- 在Activity中使用
...
LiveData<String> liveData
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LiveData<String> liveData = new LiveData<String>;
liveData.postValue("Hello");// 發消息
liveData.setValue("world");// 發消息
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
liveData.observe(MainActivity.this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i("接收到資料",s+"");
if (id == binding.button.getId()) {
binding.button.setText(s);
}
if (id == binding.button2.getId()) {
binding.button2.setText(s);
}
}
});
}
});
}
2.原理
LiveData發送資料使用
setValue
和
postValue
,它們的差別是
setValue
直接在主線程中進行,
postValue
則是在子線程進行的。是以當你的資料要在子線程發出來的,應該選用
postValue
,否則使用
setValue
。
liveData.observe(LifecycleOwner, Observer<? super T> )
這個方法是用來注冊觀察者的。注冊的過程是這樣的:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNCM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TP35UNnpXTyMGRNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4gDOxQjNwIjM4EjMxAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
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);
}
- 首先,注冊所在的控件的生命狀态是不是已銷毀了,如是就不再注冊,否則繼續注冊。
-
将我們的觀察者進行打包,打包成一個LifecycleEventObserver觀察者,這個觀察者專門用于元件生命周期的觀察的。LifecycleBoundObserver wrapper
-
最後,将觀察者注冊到元件的生命周期的可觀察對象上。
也就是說,android本身是有這個生命周期觀察機制的,這就給我們LiveData感覺元件生命周期創造了條件,我們隻是在這個機制上添加了一些我們的東西而已。
LifecycleBoundObserver的UML圖:
LifecycleEventObserver接口中有一個方法
onStateChanged
,當元件的生命周期發生改變時,就會被調用:
public interface LifecycleEventObserver extends LifecycleObserver {
/**
* Called when a state transition event happens.
*
* @param source The source of the event
* @param event The event
*/
void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
LiveData對這個方法的實作是這樣的:
@Override
public void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
也就是說,LiveData它會在這個方法裡觀察所在元件的生命狀态,如果是已銷毀的,那麼它就将觀察者移除,否則,它就會調用
activeStateChanged
方法,将資料分發出去:
void activeStateChanged(boolean newActive) {
...
if (mActive) {
dispatchingValue(this);
}
}
具體分發資料是由
dispatchingValue
來實作的
void dispatchingValue(@Nullable ObserverWrapper initiator) {
...
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
...
}
private void considerNotify(ObserverWrapper observer) {
...
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
dispatchingValue
分派事件是這樣來進行的,傳入的觀察者
initiator
不為空,則執行該觀察者的事件,否則就周遊所有觀察者,并執行它的事件。我們剛剛是注冊觀察者,是以,會執行該觀察者的事件onChanged,事件會把之前的資料拿過來,這就是所謂的粘性事件。
postValue
和
setValue
事件就會周遊所有的觀察者,進行資料分發。
postValue
和
setValue
事件都會直接去分派事件,
postValue
最後還是調回了
setValue
:
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
正如上面所見的,
postValue
和
setValue
都會修改mData的值,mData是持有需要傳遞的資料的變量。是以:
liveData.postValue("Hello");// 發消息
liveData.setValue("world");// 發消息
結果是mData = “world”
3.自定義LiveData
我們自己實作一個WnLiveData:
package com.wong.livedatademo;
import android.annotation.SuppressLint;
import androidx.annotation.NonNull;
import androidx.arch.core.executor.ArchTaskExecutor;
import androidx.arch.core.internal.SafeIterableMap;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import static androidx.lifecycle.Lifecycle.State.DESTROYED;
import static androidx.lifecycle.Lifecycle.State.STARTED;
public class WnLiveData<T> {
private Object NOT_SET = new Object();
// 存入的資料
private T mData;
// 生命周期
private LifecycleOwner owner;
// 存放觀察者對象
private Map<Observer<? super T>, WnLifecycleObserver> mObservers = new HashMap<>();
private int mVersion;
volatile Object mPendingData = new Object();
final Object mDataLock = new Object();
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
// 非主線程中使用
@SuppressLint("RestrictedApi")
public void postValue(T value) {
synchronized (mDataLock) {
mPendingData = value;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
WnLifecycleObserver wrapper = new WnLifecycleObserver(owner, observer);
mObservers.put(observer,wrapper);
owner.getLifecycle().addObserver(wrapper);
}
// 在主線程中使用
public void setValue(T value) {
mVersion++;
mData = value;
dispatchingValue(null);
}
private class WnLifecycleObserver implements LifecycleEventObserver {
final Observer<? super T> mObserver;
boolean mActive;
int mLastVersion = -1;
@NonNull
final LifecycleOwner mOwner;
private WnLifecycleObserver(@NonNull LifecycleOwner mOwner,Observer<? super T> mObserver) {
this.mObserver = mObserver;
this.mOwner = mOwner;
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
WnLifecycleObserver removed = mObservers.remove(mObserver);
return;
}
boolean newActive = mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
if (newActive == mActive) {
return;
}
mActive = newActive;
if (mActive) {
dispatchingValue(this);
}
}
}
private void dispatchingValue(WnLifecycleObserver observer) {
if (observer != null) {
notify(observer);
} else {
for (Map.Entry<Observer<? super T>, WnLifecycleObserver> observerWnLifecycleObserverEntry : mObservers.entrySet()) {
notify(observerWnLifecycleObserverEntry.getValue());
}
}
}
private void notify(WnLifecycleObserver observer) {
if (!observer.mActive) {
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
}
Demo