当前位置:网站首页>Livedata source code appreciation III - frequently asked questions

Livedata source code appreciation III - frequently asked questions

2022-06-30 11:13:00 Android daily lecture

Data loss

adopt postValue() Method update LiveData Data time , There may be data loss .

val liveData = MutableLiveData()
Thread {
    for (index in 0..9) {
        liveData.postValue("new str $index")
    }
}.start()
liveData.observe(this) {
    Log.i("LiveData", "observe: $it")
}

We called... In succession postValue()10 Time , But the result is only the last data .

LiveData: observe: new str 10

This is because postValue() In fact, the logic of data callback is put into Runnable in , Again post to Handler, utilize Handler Update... In the main thread , So from postValue() To carry out Runnable, There is a time difference in the middle . In this period of time through postValue() Method update data will only change LiveData Internal value , Not again post A new Runnable.

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() {
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        setValue((T) newValue);
    }
};

Only when Runnable Carried out mPendingData Will be assigned to NOT_SET, In this way postValue() When it comes to execution postTask = mPendingData == NOT_SET To make postTask The value of is true, At the end of the day post One Runnable.

Viscous events

If the event launched is earlier than the registration , The events that can still be received after registration are called sticky events .

LiveData The inside is through an integer mVersion To record the version number of the current data .

protected void setValue(T value) {
	// Omit other code 
    mVersion++;
}

When we call setValue() When updating data ,mVersion It's going to increase .

private abstract class ObserverWrapper {
    int mLastVersion = -1;
}

In our observer's packaging class ObserverWrapper A version number is also maintained internally mLastVersion, It records the data version of the last callback , Initialize to -1.

If we change first LiveData The data of , that mVersion It will increase and become 1, Then register the observer , At this time, the version number maintained internally by the observer mLastVersion For the initial value -1. Finally, during the callback judgment (observer.mLastVersion >= mVersion) Will not be established , So the observer will receive the data before it is registered .

private void considerNotify(ObserverWrapper observer) {
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}

Data processing

If you want to LiveData Change the value stored in the object before it is assigned to the observer , Or you need to return different values according to the value of another instance LiveData example , have access to Transformations Class LiveData Data processing of .

map

map Can be LiveData Internal data type conversion , send LiveData Convert to LiveData.

val intLiveData = MutableLiveData(1)
val strLiveData:LiveData<String> = Transformations.map(intLiveData){
    "$it"
}
strLiveData.observe(this){
    println(it is String)//true
}

switchMap

switchMap() According to a certain value , Switch and observe different LiveData data . It can also be realized LiveData Convert to LiveData.

val originLiveData = MutableLiveData(true)
val trueLiveData = MutableLiveData("trueLiveData")
val falseLiveData = MutableLiveData("falseLiveData")
val distinctLiveData = Transformations.switchMap(originLiveData) {
    if (it) {
        trueLiveData
    } else {
        falseLiveData
    }
}
distinctLiveData.observeForever {Log.i(TAG, it)}//trueLiveData

distinctUntilChanged

distinctUntilChanged() Method returns a masked primitive LiveData New... Of duplicate data LiveData.

val boolLiveData = MutableLiveData<Boolean>()
val distinctLiveData = Transformations.distinctUntilChanged(boolLiveData)
Thread {
    for (index in 0..10) {
        SystemClock.sleep(100)
        boolLiveData.postValue((index < 9))
    }
}.start()
distinctLiveData.observe(this){
    println(it) // As a result, the weight was removed    Only true  and  false   Two outputs 
}

Perception life cycle

LiveData.observer() Methods can sense Owner Life cycle of , When this method is called, a LifecycleOwner object ,LifecycleOwner It's an interface .

public interface LifecycleOwner {
    Lifecycle getLifecycle();
}

Fragment and FragmentActivity Both implement this interface and return a LifecycleRegistry object , When their life cycle changes , Would call LifecycleRegistry.handleLifecycleEvent() Method to distribute the lifecycle to the corresponding lifecycle observer . Callback LifecycleEventObserver Of onStateChanged() Method . and LifecycleBoundObserver Realized LifecycleEventObserver Interface , So he can receive the callback of life cycle change .

public interface LifecycleEventObserver extends LifecycleObserver {
    void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
原网站

版权声明
本文为[Android daily lecture]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/181/202206301039119196.html