Pay attention to avoiding pits: LiveData is "inconspicuous" and will encounter problems (Tips)

PostValue() will discard the old value

One day when I was writing a piece of logic, I used LiveData to transfer data like this:

textLiveData.postValue("1")
textLiveData.postValue("2")

As a result, only "2" was called back at the callback, so where did "1" go!

Take a look at the source code of postValue:

    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
                // 如果 mPendingData 已经有值,postTask 为 false,
            // 就不会执行下面的 postToMainThread 任务
            postTask = mPendingData == NOT_SET;
            
            // 每次 post 这里的 mPendingData 都会刷新,
            // 所以我们总是能得到最新值的回调
            mPendingData = value;
        }

        if (!postTask) {
            return;
        }
        
        // 将任务 post 到主线程 Handler 执行
                ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
    private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                    // 设置值之后将  mPendingData 重置
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            // 最终还是调的 setValue
            setValue((T) newValue);
        }
    };

postValue is to post the value to the main thread for execution, and our main thread takes the messages in the queue and processes them one by one, so the processing will not be so timely. Analyze the scenario above, the first post of a "1" at this time mPendingData = "1", postTask = truethis task is to post the main thread waiting to execute. Then post "2" again. At this time mPendingData = "2", postTask = falseonly the value of mPendingData will be modified, and the task of the main thread will be executed after mPendingData is modified to "2". So the callback we get is always the last one.

Summary : postValue is actually designed for multi-threaded environments, it is not necessary to use it in ordinary scenarios. Just use setValue directly.

LiveData callbacks caused by repeated callbacks in the life cycle

Previously, I used LiveData to pass click events between Activity and Fragment. When used in the fragment in ViewPager, it will explode. When the fragment is switched left and right, the click event is triggered.

Since LiveData always goes back to check if there is a value when the component is initialized and active, it will call back if there is a value. So if a Fragment is registered with the LiveData callback, and the Activity is repeatedly removed and then added to the Fragment, it will call back multiple LiveData callbacks. (Note: The LiveData here exists in the ViewModel of Activity, and its life cycle is longer than Fragment)

My previous solution was to set LivaData to null during fragment onDestory. In fact, it is not elegant enough, this kind of short-term news, it is meaningless to encapsulate LiveData:

After sending the message, it is set to empty immediately, and the value of a fleeting LiveData will not be saved. Here you need to make a good judgment on null:if(v == null) return

class FleetingLiveData<T> : MutableLiveData<T>() {

    override fun setValue(value: T) {
        super.setValue(value)
        super.setValue(null)
    }

    override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        super.observe(owner, Observer {
            if (it == null) return@Observer
            observer.onChanged(it)
        })
    }
}

Summary : LiveData is bound to the life cycle of a component, and the feature that it will be called back when there is a value has advantages and disadvantages. It can be used for sticky events, but if it is not used well, weird callbacks will occur, such as being used to deliver click events such as short-lived events that do not need to save values.


After reading the likes, develop a habit, search "Programming Ape Development Center" on WeChat to follow this programmer who likes to write dry goods.

In addition, there is also a complete test site for interviews with major Android first-line companies. The information is updated in my Gitee . Friends who need interviews can refer to them. If it is helpful to you, you can order a Star!

Gitee address : [ Old Chen's Gitee ]


 

Guess you like

Origin blog.csdn.net/qq_39477770/article/details/108851836