基本概念
LiveData
是一种具有生命周期感知能力的可观察数据持有类LiveData
可以保证屏幕上的显示内容和数据一直保持同步
特点
LiveData
了解UI界面的状态,如果activity不在屏幕上显示,livedata不会触发没必要的界面更新,如果activity已经被销毁,会自动清空与observer的连接
-LiveData
是一个LifecycleOwner,他可以直接感知activity或fragment的生命周期
可解决什么问题
- 感知生命周期,在active的时候接收变化
- 可以感知数据的变化并体现到UI上
- 取代eventbus,在不同界面间通过map+观察者可实现数据发送和接收
使用
class MainViewModel : BaseViewModel() {
//定义数据
val upgradeRsp = MutableLiveData<AppUpdateRspData>()
fun getData(){
//通过网络或者数据库等拿到数据后,子线程postValue(),主线程setValue()
upgradeRsp.postValue(data)
}
}
//这里是在Fragment中观察数据变化,如果是activity中的话则viewLifrcycleOwner换成this即可 upgradeRsp.observe(viewLifecycleOwner, Observer {
//更新UI等逻辑
})
工作原理
observe()方法开始跟到源码
@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;
}
//这句代码就很熟悉了,上一篇文章说LifeCycle完成观察者对被观察者的订阅
owner.getLifecycle().addObserver(wrapper);
}
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
//至少是STARTED状态,根据上一篇文档底部的图,即onStart()/onResume()/onPause()生命周期中,即为`活跃`
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
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
//如果是销毁状态则移除观察者,防止内存泄漏
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
}
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);
}
}
//如果指定了某个观察者,则只Nofify它,否则遍历所有的观察者一个个Notify之
void dispatchingValue(@Nullable ObserverWrapper initiator) {
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
xxxxxxx
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
xxxxxxx
}
}
} while (mDispatchInvalidated);
}
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);
}
到这里就讲清楚了上面说的第一个问题"感知生命周期的变化",在活跃的时候接收监听,销毁的时候移除观察者。
setValue()和postValue()
LiveData发送事件有2个方法:setValue()和postValue(),其中setValue()方法只能在主线程发,而postValue()方法可以在子线程发,Observer的onChange()始终在主线程
注释说的很清楚,只能在主线程上调用
/**
* Sets the value. If there are active observers, the value will be dispatched to them.
* <p>
* This method must be called from the main thread. If you need set a value from a background
* thread, you can use {@link #postValue(Object)}
*
* @param value The new value
*/
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
//发送一次mVersion+1,有点类似于list的modify
mVersion++;
mData = value;
//上面已经分析过了,这个方法传参为null,则所有活跃状态的观察者都会被分发,并回调到onChanged()
dispatchingValue(null);
}
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
//和setValue差不多,只不过调用了postMainThread()方法跑去主线程了,可以继续往下跟 ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
@Override
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = new Handler(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
//最终postValue()还是调用到setValue()
setValue((T) newValue);
}
};
这个方法是可以在子线程中发数据的,但是我们最后的onChanged()方法却始终在主线程的
,这是怎么做到的呢?看到这两句代码应该就很明白了
mMainHandler = new Handler(Looper.getMainLooper());
mMainHandler.post(runnable);
LivedataBus粘性事件
通过一个集合统一管理所有的LiveData
原来的执行顺序new LiveData–>绑定observer–>setValue执行onChanged
完美!
MutableLiveData<String> currentName = xxxx;
//取出livedata完成订阅
model.getCurrentName().observe(this,new Observer<String>(){
@Override
public void onChanged(String s) {
nameTextView.setText(s);
}
});
btn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
String anotherName="jett"+(i++);
model.getCurrentName().setValue(anotherName);
}
});
但是可能会有这样的情况出现:
new LiveData–>setValue执行onChanged–>绑定observer
比如这样:
先发送消息了------>
Intent intent = new Intent(this, TestLiveDataBusActivity.class);
startActivity(intent);
new Thread(){
@Override
public void run() {
for (int i = 0; i < 20; i++) {
//发送消息
LiveDataBus.getInstance().with("data", String.class).postValue("jett");
Log.e(TAG, "run:已发送 ");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
然后第二个界面才走onCreate()—>绑定观察者
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_livedatabus);
Log.e(TAG, "onCreate: " );
LiveDataBusX.getInstance().with("data", String.class)
.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.e(TAG, "onChanged: "+s);
if(s!=null)
Toast.makeText(TestLiveDataBusActivity.this, s, Toast.LENGTH_SHORT).show();
}
});
}
于是就出现了EventBus粘性事件类似的事情,至于如何解决,也不难,注意下面个方法: