導(dǎo)語(yǔ)
Jetpack簡(jiǎn)介及其它組件文章
還在擔(dān)心View層的內(nèi)存泄漏嗎狂魔?還在擔(dān)心一些空指針異常嗎?LiveData幫你解決這些問(wèn)題。
主要內(nèi)容
- LiveData是什么
- LiveData的基本使用
- postValue和setValue有什么區(qū)別
- observe是如何收到通知的
- LiveData的粘性事件
- 如何解決LiveData的粘性事件
具體內(nèi)容
LiveData是什么
- LiveData是一個(gè)數(shù)據(jù)持有類
- 能夠感知組件的生命周期
- 持有的數(shù)據(jù)可以被觀察者觀察
簡(jiǎn)單地來(lái)說(shuō)就是當(dāng)LiveData持有的數(shù)據(jù)發(fā)生改變的時(shí)候题涨,觀察者在生命周期處于STARTED或RESUMED狀態(tài)時(shí),LiveData會(huì)更新通知給活躍的觀察者菠隆。
LiveData的基本使用
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//創(chuàng)建一個(gè)LiveData
MutableLiveData<String> mutableLiveData = new MutableLiveData<>();
//注冊(cè)觀察者
mutableLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d("LiveData", s);
}
});
//其它線程執(zhí)行完任務(wù)對(duì)LiveData進(jìn)行通知
new Thread(new Runnable() {
@Override
public void run() {
//postValue() 可以在任意線程使用
mutableLiveData.postValue("通知");
//setValue() 只能在主線程被調(diào)用
// mutableLiveData.setValue("通知");
}
}).start();
}
}
從上面的代碼可以看出譬重,LiveData的基本使用很簡(jiǎn)單,同時(shí)我在代碼中注釋講setValue()
只能在主線程被調(diào)用簿训,接下來(lái)我們深入源碼再看一下咱娶。
postValue和setValue有什么區(qū)別
我們可以分別點(diǎn)擊postValue和setValue方法,進(jìn)入它們的源碼進(jìn)行觀察强品。
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
/**
* 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
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
我們可以先看setValue()
膘侮,可以看到setValue()
有個(gè)注解@MainThread
,方法上面也有注釋This method must be called from the main thread.
的榛,都表明了這個(gè)方法只能在主線程被調(diào)用琼了。
我們?cè)俑櫼幌聀ostValue方法。postValue方法執(zhí)行了一行比較重要的代碼:ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
看樣子是交給主線程去執(zhí)行一個(gè)Runnable
夫晌。我們進(jìn)入這個(gè)Runnable
看一下雕薪。
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
};
我們可以看到,Runnable
最終又調(diào)用了setValue()
晓淀。
看到這里我們就知道了所袁,postValue()
和setValue()
的作用是相同的,區(qū)別是postValue()
可以在任意線程調(diào)用凶掰,setValue()
只能在主線程調(diào)用燥爷。
因?yàn)?code>postValue()可以在任意線程調(diào)用,所以mPendingData
使用了volatile
關(guān)鍵字锄俄,同時(shí)通過(guò)synchronized
對(duì)代碼塊進(jìn)行加鎖局劲,來(lái)保證線程安全。
可以通過(guò)setValue
方法看到奶赠,mData
才是我們真正的數(shù)據(jù)持有者鱼填。
observe是如何收到通知的
我們來(lái)直接看源碼,我們先看LiveData.observe()
方法毅戈。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LiveData.LifecycleBoundObserver wrapper = new LiveData.LifecycleBoundObserver(owner, observer);
LiveData.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);
}
其中LifecycleBoundObserver
持有了我們傳入的Observer<? super T> observer
苹丸,最后放到了mObservers
這個(gè)對(duì)象了愤惰,這個(gè)對(duì)象是一個(gè)Map
,所以我們可以一對(duì)多赘理。
owner.getLifecycle().addObserver(wrapper)
這個(gè)代碼不重點(diǎn)講了宦言,這個(gè)是Lifecycle
提供的功能,如果不了解可以看我其它文章或者去網(wǎng)上找一下商模〉焱總之就是把wrapper
和LifecycleOwner
的生命周期進(jìn)行了綁定。
我們?cè)賮?lái)看setValue()
方法是如何通知的施流。
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
void dispatchingValue(@Nullable LiveData.ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, LiveData.ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
private void considerNotify(LiveData.ObserverWrapper observer) {
if (!observer.mActive) {
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);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
這段代碼比較長(zhǎng)响疚,不要慌,很簡(jiǎn)單瞪醋,有些代碼不重要直接往下看忿晕。
直接看dispatchingValue(null)
到底做了啥。首先我們傳入了null
银受,所以會(huì)走else
践盼,我們看到這里使用Iterator
對(duì)mObservers
進(jìn)行遍歷,之前說(shuō)到mObservers
是一個(gè)map
宾巍,然后取出值執(zhí)行considerNotify(iterator.next().getValue())
方法咕幻,在considerNotify()
里,最終調(diào)用observer.mObserver.onChanged((T) mData)
蜀漆,把結(jié)果回調(diào)給我們業(yè)務(wù)層谅河。
LiveData的粘性事件
我們來(lái)看一段代碼咱旱,想一下Log會(huì)如何輸出确丢。
public class MainActivity extends AppCompatActivity {
MutableLiveData<String> mutableLiveData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mutableLiveData = new MutableLiveData<>();
mutableLiveData.postValue("----------------》通知1");
}
//點(diǎn)擊事件 寫在xml里了
public void observe(View view) {
mutableLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d("LiveData", s);
}
});
mutableLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d("LiveData", s);
}
});
}
}
我們有一個(gè)點(diǎn)擊事件,放到了xml里吐限,我們先postValue()
鲜侥,通過(guò)點(diǎn)擊按鈕再注冊(cè)observer
,會(huì)怎樣呢诸典?
2021-03-10 16:52:07.251 25476-25476/com.example.jetpack D/LiveData: ----------------》通知1
2021-03-10 16:52:07.251 25476-25476/com.example.jetpack D/LiveData: ----------------》通知1
居然也收到了通知描函,這是為什么呢?我們來(lái)通過(guò)源碼看一下狐粱。
我們?cè)?code>LiveData.observe()的時(shí)候舀寓,創(chuàng)建了LifecycleBoundObserver
,LifecycleBoundObserver
繼承ObserverWrapper
肌蜻,我們直接來(lái)看LifecycleBoundObserver
和ObserverWrapper
的代碼互墓。
class LifecycleBoundObserver extends LiveData.ObserverWrapper implements GenericLifecycleObserver {
//...
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
//...
}
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() {
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
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);
}
}
}
LifecycleBoundObserver
最終還繼承了LifecycleEventObserver
,LifecycleEventObserver
有一個(gè)方法onStateChanged()
蒋搜,首先要了解onStateChanged()
方法是Lifecycle
提供的功能篡撵,如果不了解可以看我其它文章或者去網(wǎng)上找一下判莉。總之就是在Lifecycle
的生命周期發(fā)生改變的時(shí)候調(diào)用育谬,所以當(dāng)LiveData.observer()
的時(shí)候券盅,就會(huì)調(diào)用到onStateChanged()
,然后再調(diào)用到activeStateChanged()
膛檀,最終執(zhí)行了dispatchingValue(this)
锰镀,這句很熟悉呀,就是和setValue()
最終執(zhí)行的是一樣的代碼塊咖刃。不同的是傳入的參數(shù)不為空了互站,所以直接執(zhí)行considerNotify(initiator)
,不用遍歷了僵缺。我們?cè)賮?lái)看一下這個(gè)方法我們還沒(méi)有講到的地方胡桃。
private void considerNotify(LiveData.ObserverWrapper observer) {
if (!observer.mActive) {
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);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
我們一直向下走,直接來(lái)到considerNotify
方法磕潮,重要的一行代碼是observer.mLastVersion >= mVersion
翠胰,分別點(diǎn)擊兩個(gè)version
去看一下,就明白了自脯,分別是ObserverWrapper
的版本號(hào)和LiveData
的版本號(hào)之景,ObserverWrapper
的版本號(hào)大于LiveData
的版本號(hào)時(shí),我們就返回膏潮,反之則執(zhí)行锻狗,也就是說(shuō)在什么情況下會(huì)執(zhí)行呢?
舉例我們剛才的事例代碼焕参,當(dāng)LiveData
創(chuàng)建的時(shí)候轻纪,mVersion
的版本號(hào)為-1
,當(dāng)LiveData
執(zhí)行setValue
的時(shí)候叠纷,執(zhí)行mVersion++
結(jié)果為0
刻帚,剛創(chuàng)建ObserverWrapper
的時(shí)候,mLastVersion
的版本是-1
涩嚣,這個(gè)時(shí)候-1 >= 0
的結(jié)果為false
崇众,所以向下執(zhí)行不會(huì)return
,把mVersion
賦值給ObserverWrapper
的mLastVersion
航厚,防止多次被回調(diào)顷歌,最終執(zhí)行observer.mObserver.onChanged((T) mData)
。
如何解決LiveData的粘性事件
網(wǎng)上大多數(shù)的方案是通過(guò)反射幔睬,在第一次observer
的時(shí)候眯漩,修改ObserverWrapper
的mLastVersion
的值。
我的解決方案有點(diǎn)不太一樣溪窒,通過(guò)代理模式攔截observer
坤塞。
我也上傳到github了冯勉,可以給俺點(diǎn)幾個(gè)小星星,謝謝摹芙。
/**
* Created by guoshichao on 2021/3/10
* 非粘性LiveData事件
*/
public class NonStickyLiveData<T> extends MutableLiveData<T> {
static final int START_VERSION = -1;
private int mVersion = START_VERSION;
@Override
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
ObserverProxy observerProxy = new ObserverProxy<>(observer);
observerProxy.preventNextEvent = mVersion > START_VERSION;
super.observe(owner, observerProxy);
}
@Override
public void setValue(T value) {
mVersion++;
super.setValue(value);
}
private class ObserverProxy<T> implements Observer<T> {
@NonNull
private final Observer<T> observer;
private boolean preventNextEvent = false;
ObserverProxy(@NonNull Observer<T> observer) {
this.observer = observer;
}
@Override
public void onChanged(@Nullable T t) {
if (preventNextEvent) {
preventNextEvent = false;
return;
}
observer.onChanged(t);
}
}
}
如果這樣寫有問(wèn)題或者會(huì)出現(xiàn)bug灼狰,歡迎大家聯(lián)系我。