天天看點

Jetpack ——LiveData初識到源碼解析(一)

上篇部落格分享了下Lifecycle,使用的技術也就是:觀察者模式+注解+反射。本篇部落格繼續學習Jetpack的LiveData,其實這個東西是一種可觀察的資料存儲類。

LiveData自己可以作為觀察者,觀察到資料變化,并回調給開發者。 它是可以監聽到Activity(Fragment)生命周期的變化,并且在Activity處于活躍狀态下,才發送時間通知開發者處理業務邏輯。

LiveData官網

這個LiveData不是資料,是資料存儲類。

LiveData的使用

示例:一個按鈕,一個TextView , 點選一個按鈕,TextView的值+1。

LiveData一般是結合ViewModel使用的,關于ViewModel,之後的部落格再分享。 先建立一個類繼承自ViewModel:

/**
 * author: liumengqiang
 * Date : 2020/5/14
 * Description :
 */
public class NameViewModel extends ViewModel {

	//MutableLiveData繼承自LiveData
    private MutableLiveData<String> name;

	//暴露擷取方法
    public MutableLiveData<String> getName() {
        if(name == null) {
            name = new MutableLiveData<>();
        }
        return name;
    }
}
           

使用的話就很簡單了, 在Activity的onCreate方法中:

private int index = 0;

    private TextView nameTextView;

    private Button btn;

    private NameViewModel nameViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_live_data);
		//擷取或者建立ViewModel
        nameViewModel =
                new ViewModelProvider(this,
                        new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(NameViewModel.class);

		//綁定LiveData到一個觀察者上
        nameViewModel.getName().observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                nameTextView.setText(s);
            }
        });

        nameTextView = findViewById(R.id.live_data_text);
        btn = findViewById(R.id.live_data_btn);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
            	//資料源改變
                String name = "hello world " + (index ++);
                nameViewModel.getName().setValue(name);
            }
        });
    }
           

這個代碼就很簡單了,結果如下圖:

Jetpack ——LiveData初識到源碼解析(一)

這個例子是很簡單的,LiveData強大之處就是: 既可以作為觀察者,也可以作為被觀察者。

作為觀察者:能夠感覺Activity或者Fragment的生命周期的變化。

作為被觀察者:當資料改變能夠通知給開發者,以處理業務邏輯。

其内部原理是怎樣的呢?

LiveData源碼分析

在分析源碼之前我們看三個結論,

  • LiveData是能夠感覺元件生命周期的,當Activity處于活躍狀态時,才能夠收到資料,不處于活躍狀态是收不到事件的。
  • LiveData在元件處于DESTROYED狀态下會移除Observer,解除綁定,避免記憶體洩漏
  • 每次調用setValue更改資料源之後,如果元件從非活躍狀态到活躍狀态,元件此時接收到的是最新的資料,而中間發的很多的次變更都是無效的。

首先我們從訂閱開始:

@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    	//檢測是否在主線程
        assertMainThread("observe");
        //判斷元件是否是DESTROYED狀态。
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //将元件和Observer封裝成一個對象:LifecycleBoundObserver
        //這個對象實作了LifecycleObserver接口
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //把所有的Observer和封裝的對象添加到了集合中
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
       	......
       	//這個是把LifecycleObserver實作對象和 元件綁定起來
       	//這樣就能夠感覺元件的生命周期了。
        owner.getLifecycle().addObserver(wrapper);
    }
           

這裡做了主要三件事

  1. 檢測元件是否是處于DESTORYED狀态, 如果是,就直接傳回
  2. 将元件和Observer封裝成了一個LifecycleObserver實作類對象,這個對象,存到了一個map中,這樣友善之後setValue分發資料
  3. 最後将LifecycleObserver實作類對象群組件綁定在一起,這樣能夠感覺元件的生命周期變化了。

現在看下setValue方法,也就是改變LiveData裡面的資料源

//從這個注解可以看出來必須要在主線程調用
    @MainThread
    protected void setValue(T value) {
    	// 檢測是否在主線程
        assertMainThread("setValue");
        //定義了一個版本号
        mVersion++;
        //将值指派給mData變量
        mData = value;
       	//開始分發資料事件
        dispatchingValue(null);
    }
           

代碼注釋比較清晰了,主要是這個版本号:mVersion是個什麼東西呢? 為什麼定義這個東西呢? mVersion就是記錄一下改變次數,每次setValue方法調用,也就是每次資料源改變,mVersion都會+1, 這個值接下來會和LifecycleBoundObserver實作類的mLastVersion對比的,具體下文解釋。

然後将value值指派給了mData對象,這樣的話,試想一下,如果若此調用setValue方法,每次set 的值都不一樣,那麼是不是mData存儲的都是最後一次setValue的值呢? 答案是肯定的,存儲的就是最後一次setValue的值。

然後現在開始分發資料源改變的事件:

@SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
      ........
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
            	//initiator不是null, 也就是定向分發事件,
                considerNotify(initiator);
                initiator = null;
            } else {
            	//initiator是null
            	//	循環之前map, 然後給每個觀察者都分發事件
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }
           

由于此時傳入的dispatchingValue傳入的參數是null,是以是全部的觀察者都分發事件。

傳入initiator不是null的情況是在生命周期改變的情況下執行的,下文具體分析
private void considerNotify(ObserverWrapper observer) {
        //判斷是否是處于活躍狀态
        //是否是已經解綁
        if (!observer.mActive) {
            return;
        }
        //活躍狀态是:STARTED或者RESUMED
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        //判斷Observer的mLastVersion和mVersion的大小
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        //給Observer的mLastVersion重新指派
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        //執行觀察者的onChaned回調
        observer.mObserver.onChanged((T) mData);
    }
           

這裡的ObserverWrapper observer對象實際上就是LifecycleBoundObserver, 這個在剛開始訂閱的時候内部建立的。它繼承自ObserverWrapper

LifecycleBoundObserver也實作了GenericLifecycleObserver,而GenericLifecycleObserver繼承自LifecycleEventObserver, 這個細節很重要,具體後續的代碼會着重分析。
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @NonNull
        final LifecycleOwner mOwner;

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

		//判斷是否是活躍狀态:STARTED或者RESUMED,
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

		//這個方法就是元件生命周期改變時, 調用的方法。傳入的參數一個是元件本身,一個是元件處于的狀态
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        	//當元件處于DESTROYED狀态時,也就是處于銷毀狀态時
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            	//移除Observer,解除綁定
                removeObserver(mObserver);
                return;
            }
            //這個方法的實作是在父類ObserverWrapper中的
            activeStateChanged(shouldBeActive());
        }

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

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

從LifecycleBoundObserver的具體實作,需要注意兩個知識點

  1. shouldBeActive方法是傳回元件是否:STARTED或者RESUMED狀态,如果是就傳回true
  2. onStateChanged方法是分析LiveData感覺元件生命周期的重要點,具體我們下文分析。

在onStateChanged方法中調用了父類的activeStateChanged方法,看下具體實作:

void activeStateChanged(boolean newActive) {
       		//判斷活躍狀态是否等于上一次的狀态
            if (newActive == mActive) {
                return;
            }
            ......
           //
            if (mActive) {
            	//如果是活躍狀态,那麼就分發資料源改變事件,傳入的參數是自己本身,
            	//也就是:LifecycleBoundObserver類的對象
                dispatchingValue(this);
            }
        }
    }
           

這時候對于dispatchingValue方法傳入的參數不是null, 是不是就是單次分發呢? 懵逼的,重新網上看下dispatchingValue方法。,進入到了if判斷裡面。

重新回到considerNotify方法,mLastVersion和mVersion的初始值都是-1, 但是每次setValue, mVersion的值都會+1, 但是mLastVersion的值還是-1, 是以(observer.mLastVersion >= mVersion) 不成立,将mVersion的值指派給mLastVersion, 這樣mLastVersion就是最新的值了, 最後調用了我們熟悉的onChanged方法。

想一下considerNotify方法中為什麼會有這三個if判斷呢?

首先前兩個判斷就是要保證元件處于活躍狀态; 此三個判斷就是要保證隻接受最後一次的新資料,并且隻執行一次。 Google這樣設計也是相當的巧妙!

這樣每次setValue 到 執行onChange方法流程就分析完了。

那麼它是怎樣感覺生命周期的呢? 換句話說就是LifecycleBoundObserver的onStateChanged方法是什麼時候執行的呢?

這個問題,如果是看過Lifecycle源碼的,這個問題是相當簡單的。

Lifecycle源碼分析

記不記得我們剛開始調用LiveData的observe方法的時候,該方法的最後一句話:

owner.getLifecycle().addObserver(wrapper);
           

把封裝成的LifecycleBoundObserver類對象群組件綁定到了一塊, 這樣内部就通過 ReportFragment就能夠感覺生命周期的變化了。詳見:Lifecycle源碼分析

這裡需要注意的一點是,當生命周期變化的時候,最終調用的dispatchEvent方法:

static class ObserverWithState {
        State mState;
        LifecycleEventObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, State initialState) {
        	//這裡傳回的直接是将observer轉成了LifecycleEventObserver。
            mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
            mState = initialState;
        }

        void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            //調用了觀察者的onStateChanged方法
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
    }
           

這裡的observer參數就是LifecycleBoundObserver類對象,上文說過LifecycleBoundObserver實作了LifecycleEventObserver接口,

Lifecycling.lifecycleEventObserver(observer);

内部執行一通邏輯之後,做的操作是直接将observer轉成了LifecycleEventObserver接口對象。

ReportFragment生命周期的變化之後,調用的是LifecycleBoundObserver的onStateChanged方法,這樣是不是形成了閉環?!

重新理一下步驟:

setValue ——> onChanged流程

  1. 通過調用LiveData的observe方法,建立了LifecycleBoundObserver對象,并且綁定了元件和LifecycleBoundObserver執行個體。
  2. 每次setValue之後會調用dispatchingValue方法
  3. 在dispatchingValue方法内,會調用considerNotify方法
  4. 在considerNotify方法内,回到用觀察者的onChanged方法。

感覺LiveData生命周期流程

  1. 通過調用LiveData的observe方法, 在這個方法最後一句話,綁定了元件和LifecycleBoundObserver類的執行個體對象。
  2. LifecycleRegister的addObserver方法内,将LifecycleBoundObserver類執行個體存儲到了一個map中。
  3. 在元件的内部建立了一個空白的ReportFragment, ReportFragment的生命周期是群組件的生命周期是同步的。
  4. 以Report Fragment的onStart方法為例: 内部調用了

    dispatch(Lifecycle.Event.ON_START);

  5. dispatch方法内調用handleLifecycleEvent方法, 該方法是在LifecycleRegister類内部的
  6. handleLifecycleEvent ——》 moveToState ——》 sync ——》 forwardPass ——》 dispatchEvent ——》 mLifecycleObserver.onStateChanged
  7. 最後回到了LifecycleBoundObserver的onStateChanged方法内,調用:activeStateChanged方法
  8. activeStateChanged ——》 dispatchingValue ——》 considerNotify ——》onChanged方法

這樣整個流程就完全了, 可能感覺生命周期的流程比較懵逼的話,一定要看一下:Lifecycle源碼分析