天天看點

LiveData的使用及原理

LiveData的使用及原理

    • 1.LiveData的使用
    • 2.原理
    • 3.自定義LiveData

LiveData是一個 可觀察的資料持有類,它與常見的可觀察對象不同的是它有生命周期意識,即它能夠感覺元件,如activities, fragments, services等的生命周期變化。以前我們可會用EventBus來做事件傳遞,現在用LiveData也是不錯。

1.LiveData的使用

  • 使用添加依賴項grale.build(:app)
dependencies {
    ...
    def lifecycle_version = "2.2.0"
    implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
}
           
  • 在Activity中使用
...
LiveData<String> liveData
@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	LiveData<String> liveData = new LiveData<String>;
	liveData.postValue("Hello");// 發消息
	liveData.setValue("world");// 發消息
	button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                liveData.observe(MainActivity.this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                Log.i("接收到資料",s+"");
                if (id == binding.button.getId()) {
                    binding.button.setText(s);
                }
                if (id == binding.button2.getId()) {
                    binding.button2.setText(s);
                }

            }
        });
	}
  });
}
           

2.原理

LiveData發送資料使用

setValue

postValue

,它們的差別是

setValue

直接在主線程中進行,

postValue

則是在子線程進行的。是以當你的資料要在子線程發出來的,應該選用

postValue

,否則使用

setValue

liveData.observe(LifecycleOwner, Observer<? super T> )

這個方法是用來注冊觀察者的。注冊的過程是這樣的:

LiveData的使用及原理
@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        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);
    }
           
  1. 首先,注冊所在的控件的生命狀态是不是已銷毀了,如是就不再注冊,否則繼續注冊。
  2. LifecycleBoundObserver wrapper

    将我們的觀察者進行打包,打包成一個LifecycleEventObserver觀察者,這個觀察者專門用于元件生命周期的觀察的。
  3. 最後,将觀察者注冊到元件的生命周期的可觀察對象上。

    也就是說,android本身是有這個生命周期觀察機制的,這就給我們LiveData感覺元件生命周期創造了條件,我們隻是在這個機制上添加了一些我們的東西而已。

LifecycleBoundObserver的UML圖:

LiveData的使用及原理

LifecycleEventObserver接口中有一個方法

onStateChanged

,當元件的生命周期發生改變時,就會被調用:

public interface LifecycleEventObserver extends LifecycleObserver {
    /**
     * Called when a state transition event happens.
     *
     * @param source The source of the event
     * @param event The event
     */
    void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
           

LiveData對這個方法的實作是這樣的:

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

也就是說,LiveData它會在這個方法裡觀察所在元件的生命狀态,如果是已銷毀的,那麼它就将觀察者移除,否則,它就會調用

activeStateChanged

方法,将資料分發出去:

void activeStateChanged(boolean newActive) {
...
	if (mActive) {
    	dispatchingValue(this);
    }
}
           

具體分發資料是由

dispatchingValue

來實作的

void dispatchingValue(@Nullable ObserverWrapper initiator) {
...
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
...
}
private void considerNotify(ObserverWrapper observer) {
     	...
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }
           

dispatchingValue

分派事件是這樣來進行的,傳入的觀察者

initiator

不為空,則執行該觀察者的事件,否則就周遊所有觀察者,并執行它的事件。我們剛剛是注冊觀察者,是以,會執行該觀察者的事件onChanged,事件會把之前的資料拿過來,這就是所謂的粘性事件。

postValue

setValue

事件就會周遊所有的觀察者,進行資料分發。

postValue

setValue

事件都會直接去分派事件,

postValue

最後還是調回了

setValue

private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };
protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
           

正如上面所見的,

postValue

setValue

都會修改mData的值,mData是持有需要傳遞的資料的變量。是以:

liveData.postValue("Hello");// 發消息
liveData.setValue("world");// 發消息
           

結果是mData = “world”

3.自定義LiveData

我們自己實作一個WnLiveData:

package com.wong.livedatademo;

import android.annotation.SuppressLint;

import androidx.annotation.NonNull;
import androidx.arch.core.executor.ArchTaskExecutor;
import androidx.arch.core.internal.SafeIterableMap;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

import static androidx.lifecycle.Lifecycle.State.DESTROYED;
import static androidx.lifecycle.Lifecycle.State.STARTED;

public class WnLiveData<T> {
    private Object NOT_SET = new Object();
    // 存入的資料
    private T mData;
    // 生命周期
    private LifecycleOwner owner;
    // 存放觀察者對象
    private Map<Observer<? super T>, WnLifecycleObserver> mObservers = new HashMap<>();
    private int mVersion;
    volatile Object mPendingData = new Object();
    final Object mDataLock = new Object();

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

    // 非主線程中使用
    @SuppressLint("RestrictedApi")
    public void postValue(T value) {
        synchronized (mDataLock) {
            mPendingData = value;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            return;
        }
        WnLifecycleObserver wrapper = new WnLifecycleObserver(owner, observer);
        mObservers.put(observer,wrapper);
        owner.getLifecycle().addObserver(wrapper);
    }


    // 在主線程中使用
    public void setValue(T value) {
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }




    private class WnLifecycleObserver implements LifecycleEventObserver {

        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = -1;

        @NonNull
        final LifecycleOwner mOwner;

        private WnLifecycleObserver(@NonNull LifecycleOwner mOwner,Observer<? super T> mObserver) {
            this.mObserver = mObserver;
            this.mOwner = mOwner;
        }

        @Override
        public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                WnLifecycleObserver removed = mObservers.remove(mObserver);
                return;
            }
            boolean newActive = mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
            if (newActive == mActive) {
                return;
            }
            mActive = newActive;
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

    private void dispatchingValue(WnLifecycleObserver observer) {
        if (observer != null) {
            notify(observer);
        } else {
            for (Map.Entry<Observer<? super T>, WnLifecycleObserver> observerWnLifecycleObserverEntry : mObservers.entrySet()) {
                notify(observerWnLifecycleObserverEntry.getValue());
            }
        }
    }

    private void notify(WnLifecycleObserver observer) {
        if (!observer.mActive) {
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }
}

           

Demo