亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

LiveData源碼分析

發布時間:2020-05-30 00:51:05 來源:網絡 閱讀:1350 作者:sq5b964702d8b05 欄目:移動開發

前言

最近的項目重構中加入LiveData框架,并且小碼的T-MVVM也是用了LiveData框架,好不好用你試試就知道(小碼口頭禪),對于LiveData使用的時候并未做太多的理解,于是乎翻了翻LiveData源代碼,在此做下筆記,

什么是LiveData
LiveData是一個數據持有類。它具有以下特點:

  • 數據可以被觀察者訂閱;
  • 能夠感知組件(Fragment、Activity、Service)的生命周期;
  • 只有在組件出于激活狀態才會通知觀察者有數據更新;

LiveData能為我們做什么

  • 能夠保證數據和UI統一,LiveData采用了觀察者模式,LiveData是被觀察者,當數據有變化時會通知UI。
    • 減少內存泄漏,LiveData能夠感知到組件的生命周期,當組件處于DESTROYED狀態時,觀察者對象會被清除,當Activity停止時不會導致Crash,因為組件處于非激活狀態時,不會收到LiveData中數據變化的通知。
    • 不需要額外的手動處理來響應生命周期的變化,因為LiveData能夠感知組件的生命周期,所以就完全不需要在代碼中告訴LiveData組件的生命周期狀態。
    • 組件和數據相關的內容能實時更新,組件在前臺的時候能夠實時收到數據改變的通知,當組件從后臺到前臺來時,LiveData能夠將最新的數據通知組件,因此保證了組件中和數據相關的內容能夠實時更新。
      若果橫豎屏切換(configuration change)時,不需要額外的處理來保存數據,當屏幕方向變化時,組件會被recreate,然而系統并不能保證你的數據能夠被恢復的。當我們采用LiveData保存數據時,因為數據和組件分離了。當組件被recreate,數據還是存在LiveData中,并不會被銷毀。
    • 資源共享.

接下來先從使用玩起,

  • 使用LiveData對象,
  • 繼承LiveData類,如MutableLiveData,
    發起數據通知2種方式:postValue和setValue:

             private MutableLiveData<String> mData=new MutableLiveData();
                mBookData.postValue("Hello LiveData");
                // mBookData.setValue("Hello LiveData");

此處postValue和setValue的區別,下文會提,
注冊觀察者并監聽數據變化:

 mData.observe(this, new Observer<String>() {
        @Override
        public void onChanged(@Nullable String str) {
          Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
        }
    });

使用非常簡單,僅此而已
通過observe方法注冊觀察者,哪咋們就看看observe里面具體干了什么,源代碼165行走起,

   //注冊觀察
 @MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {

    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);
}

observe方法接收2個參數,一個是具有生命周期的LifecycleOwner,另一個是觀察者Observer<T> ,首先判斷LifecycleOwner當前的生命周期是否為Destroyed,如果是則直接 return;如果不等于Destroyed,接下來往下看, 此處new了一個內部類LifecycleBoundObserver對象并且構造方法傳入了具有生命周期的LifecycleOwner和觀察者,這是個什么鬼,看看他的具體方法,LifecycleBoundObserver繼承自ObserverWrapper,并實現GenericLifecycleObserver,而GenericLifecycleObserver繼承了LifecycleObserver接口。由此可以看出LifecycleBoundObserver類就是把Observer和生命周期關聯起來,ok,那我們先看看LifecycleBoundObserver方法,源代碼349行走起,

   class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
    @NonNull final LifecycleOwner mOwner;

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
        super(observer);
        mOwner = owner;
    }

    @Override
    boolean shouldBeActive() {
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());
    }

    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}

此方法中,我們先看onStateChanged()方法,當生命周期變化時會回調,如果getCurrentState() == DESTROYED則removeObserver,反之則調用父類ObserverWrapper的activeStateChanged()方法,源代碼382行走起,

 private abstract class ObserverWrapper {
    final Observer<T> mObserver;
    boolean mActive;
    int mLastVersion = START_VERSION;

    ObserverWrapper(Observer<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);
        }
    }
}

activeStateChanged()是干嘛的,首先判斷activeState新舊狀態是否相同,不同則把新的狀態賦給mActive,是生命周期狀態處于ACTIVE情況下的邏輯處理。如果新的狀態和舊的狀態相同則直接返回。這里有個常量LiveData.this.mActiveCount,看注釋可以理解為觀察者處于活動狀態
個數,往下看 if (wasInactive && mActive)如果mActiveCount=0并且mActive為true,即觀察者處于活動狀態
個數從0變為1個則調用onActive(); 觀察者處于活動狀態
個數從1變為0時則調用onInactive()。然而onActive(),onInactive()并沒有任何實現代碼。好了,接下來繼續往下看dispatchingValue(this);應該就是數據變化消息調度。源代碼112行走起,

  private void dispatchingValue(@Nullable 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<T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

前面的幾行if 判斷姑且先不看,先看從if(initiator != null)開始看,如果initiator!= null調用considerNotify(initiator)方法;源代碼91行走起,

    private void considerNotify(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);
}

看見沒有最后一行代碼 observer.mObserver.onChanged((T) mData); Observer的數據變化回調;好了我們再回過頭看看initiator == null的邏輯,

   for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }

如果initiator == null 則會通過迭代器mObservers遍歷獲取ObserverWrapper,最終還是調用considerNotify方法;既然有取ObserverWrapper,咋們再看看在哪兒存的,在源碼171行:

  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);

mObservers.putIfAbsent(observer, wrapper)存入容器中,mObservers.putIfAbsent這個添加數據的方式貌似很少見,于是乎在看看mObservers是個什么數據容器,成員變量中:

   private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers =
        new SafeIterableMap<>();

這是個什么鬼,貌似以前很少見,查閱資料發現:
SafeIterableMap有以下特性:
1;支持鍵值對存儲,用鏈表實現,模擬成Map的接口
2:支持在遍歷的過程中刪除任意元素,不會觸發ConcurrentModifiedException
3:非線程安全
感興趣的可自行查閱,此處不再詳細介紹,
最后addObserver添加注冊。

下面在看看數據發起通知的邏輯,數據發起通知有2中方式:

  public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
       super.postValue(value);
    }

   @Override
   public void setValue(T value) {
       super.setValue(value);
   }
 }

setValue和postValue2中方式,我們先看看setValue代碼:

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

private static void assertMainThread(String methodName) {
    if (!ArchTaskExecutor.getInstance().isMainThread()) {
        throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                + " thread");
    }
}

setValue第一行代碼 assertMainThread("setValue");則是判斷是否在主線程,所以貌似setValue方式必須在主線程中執行,如果非主線程則拋出異常。
再看看postValue:

 protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

則postValue調用postToMainThread方法,最終還是用過setValue方式:

  private final Runnable mPostValueRunnable = new Runnable() {
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        //noinspection unchecked
        setValue((T) newValue);
    }
};

因此最終明白為什么setValue方法只能在主線程中調用,postValue可以在任何線程中調用,如果是在后臺子線程中更新LiveData的值,必須調用postValue。

至此大概明白了LiveData是干嘛的 ,怎么干的,總的來說還是很好用的,于是乎就有個小小的想法,平時用Eventbus,RxBus什么的,貌似感覺LiveData也可以實現事件總線,既然有了想法,那就干唄,

/**
 * 事件總線
 *
 * @author:tqzhang on 18/9/11 17:22
 */
 public class LiveBus {

    private static volatile LiveBus instance;

    private final Map<Object, MutableLiveData<Object>> mLiveBus;

    private LiveBus() {
       mLiveBus = new HashMap<>();
    }

    public static LiveBus getDefault() {
        if (instance == null) {
            synchronized (LiveBus.class) {
               if (instance == null) {
                   instance = new LiveBus();
                }
            }
        }
       return instance;
   }

    /**
     *
     * subscriber 注冊時間 key
     */
   public <T> MutableLiveData<T> subscribe(Object subscriber, Class<T> tMutableLiveData) {
      checkNotNull(subscriber);
      checkNotNull(tMutableLiveData);
      if (!mLiveBus.containsKey(subscriber)) {
          mLiveBus.put(subscriber, new MutableLiveData<>());
      }
      return (MutableLiveData<T>) mLiveBus.get(subscriber);

  }
}

簡單的50行代碼實現類似Eventbus,RxBus的功能,小碼親測了,挺好使的。

 //發起通知
LiveBus.getDefault().subscribe("livedata",String.class).postValue("hello LiveData");

//注冊觀察
LiveBus.getDefault().subscribe("livedata",String.class).observe(this, new Observer<String>() {
        @Override
        public void onChanged(@Nullable String s) {
            Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();
        }
    });
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

得荣县| 平山县| 措勤县| 启东市| 新建县| 饶平县| 绥芬河市| 福鼎市| 文安县| 那曲县| 长顺县| 义乌市| 都安| 苏州市| 江津市| 赣榆县| 什邡市| 大兴区| 瓦房店市| 竹山县| 东兴市| 阿荣旗| 闸北区| 武陟县| 沁阳市| 河源市| 浦北县| 通许县| 济阳县| 莲花县| 汝南县| 连江县| 竹北市| 都匀市| 芜湖县| 藁城市| 靖边县| 汝州市| 保定市| 阳朔县| 台北县|