Jetpack学习-LiveData
个人博客
Jetpack学习-LiveData
LiveData是什么
LiveData是一种可观察的数据存储器类,具有生命周期的感知能力。
简单使用
LiveData
一般都是和ViewModel一起使用。定义一个类继承自ViewModel
:
public class LiveDataSub extends ViewModel {
private MutableLiveData<String> infos;
private int number;
public MutableLiveData<String> getInfo() {
if (infos == null) {
infos = new MutableLiveData<>();
}
return infos;
}
public int increaseNumber() {
number++;
return number;
}
}
在这个类里定义MutableLiveData
类型的属性,并提供外界访问的方法getInfo
在Activity中使用
public class LiveDataActivity extends AppCompatActivity {
private TextView tv;
private LiveDataSub viewModel;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_livedata);
tv = findViewById(R.id.tv);
viewModel = ViewModelProviders.of(this).get(LiveDataSub.class);
viewModel.getInfo().observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
tv.setText(s);
}
});
}
public void update(View view) {
String info = "info:" + viewModel.increaseNumber();
viewModel.getInfo().setValue(info);
}
}
通过ViewModelProviders.of(this).get(LiveDataSub.class
)来实例化刚才定义的ViewModel
,然后通过调用LiveData
的observe
方法添加对当前Activity的观察。
通过LiveData的setValue
可以来更新数据,此时界面会自动更新。
原理
从LiveData的observe方法来看
添加observer
@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);
}
observe方法的调用要求是在主线程。如果Activity对应的lifecycle已经处于DESTROYED
状态,则会直接返回,不添加observer。最终还是调用了Lifecycle
的addObserver
方法。
数据更新
数据更新,是通过LiveData
的setValue
方法来执行的。
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
这个方法要求在主线程上执行。方法内部调用了dispatchingValue
方法
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<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
由于之前传入的ObserverWrapper
为null,因此会执行下面的迭代里的considerNotify
方法
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的onChange
方法。
时序图:
数据异步更新
上面的数据更新是在UI线程上执行的,如果想要在子线程上执行,那么则需要通过postValue
方法。我们也来看一下这个方法
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
//判断mPendingData是否已经赋值
postTask = mPendingData == NOT_SET;
//给mPendingData赋值
mPendingData = value;
}
//如果已经赋值,则取消发送
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
这个方法是通过ArchTaskExecutor的postToMainThread
方法来执行的。
先看ArchTaskExecutor.getInstance()
方法
public static ArchTaskExecutor getInstance() {
if (sInstance != null) {
return sInstance;
}
synchronized (ArchTaskExecutor.class) {
if (sInstance == null) {
sInstance = new ArchTaskExecutor();
}
}
return sInstance;
}
再来看下构造方法
private ArchTaskExecutor() {
mDefaultTaskExecutor = new DefaultTaskExecutor();
mDelegate = mDefaultTaskExecutor;
}
在这里实例化了mDefaultTaskExecutor
和mDelegate
调用postToMainThread
方法
@Override
public void postToMainThread(Runnable runnable) {
mDelegate.postToMainThread(runnable);
}
执行的是DefaultTaskExecutor
的postToMainThread
方法
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = new Handler(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
可以看到,其实就是post了一个runnable
到主线程中。
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
//获取要更新的数据
newValue = mPendingData;
//mPendingData重置
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
};
最终回调run方法里,还是调用的setValue
方法。在run方法中,会获取要更新的数据,然后对mPendingData重置。因此,如果调用了多次postValue,如果前面的更新还没有处理,则并不会往主线程发送更新的消息,只会给mPendingData赋值,在run回调中,就会获取到最后一次的数据。
上一篇: 排序(四)希尔排序的两种不同实现
下一篇: PHP的应用——聊天室开发完全手册(三)