Android開發 SingleLiveEvent解決LiveData或者MutableLiveData多次回調的問題


前言

  只要使用過一段時間的LiveData就會發現,LiveData會經常多次回調數據。我們經常碰到的這個問題。

問題復現

    我們的ViewModel里是給Activity持有的並且里面有一個LiveData數據,我們A_Fragment現在獲得Activity的ViewModel並且注冊LiveData數據成為觀察者,這個時候我們setValue()就會讓前台的A_Fragment得到一次LiveData數據,接下來操作 A_Fragment 啟動 B_Fragment,在返回到A_Fragment。 你會發現只要再次注冊LiveData的observe(this, new Observer ...),那么A_Fragment里面又會接收到一次LiveData的數據。

為什么會這樣呢?

  1.一部分原因是LiveData的機制,就是向所有前台Fragment或者Activity發送數據。只要注冊的觀察者在前台就必定會收到這個數據。

  2.另一部分的原因是對ViewModel理解不深刻,理論上只有在Activity保存的ViewModel它沒被銷毀過就會一直給新的前台Fragment觀察者發送數據。我們需要管理好ViewModel的使用范圍。 比如只需要在Fragment里使用的ViewModel就不要給Activity保管。而根Activity的ViewModel只需要做一下數據共享與看情況使用LiveData。

 

解決問題

第一種方法

就是管理好ViewModel的范圍,如果業務范圍只跟某個Fragment有關,那么最好就只給這個Fragment使用。這樣Fragment在銷毀或者創建的時候,也會銷毀ViewModel與創建ViewModel,ViewModel攜帶的LiveData就是全新的不會在發送之前設置的數據。

第二種方法

就是使用一個google大神實現的一個復寫類 SingleLiveEvent,其中的機制是用一個原子 AtomicBoolean記錄一次setValue。在發送一次后在將AtomicBoolean設置為false,阻止后續前台重新觸發時的數據發送。

import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;

import java.util.concurrent.atomic.AtomicBoolean;

public class SingleLiveEvent<T> extends MutableLiveData<T> {
    private final AtomicBoolean mPending = new AtomicBoolean(false);
    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer<? super T> observer) {
        super.observe(owner, new Observer<T>() {
            @Override
            public void onChanged(@Nullable T t) {
                if (mPending.compareAndSet(true, false)) {
                    observer.onChanged(t);
                }
            }
        });
    }

    @MainThread
    public void setValue(@Nullable T t) {
        mPending.set(true);
        super.setValue(t);
    }

    /**
     * Used for cases where T is Void, to make calls cleaner.
     */
    @MainThread
    public void call() {
        setValue(null);
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM