1.LiveData是什么?
只有在生命周期处于started和resumed时。livedata才会更新观察者
2.Livedata的各种使用方式
1.更新数据
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView : TextView = findViewById(R.id.tv_textview)
// 1 观察者 眼睛 环节
MyLiveData.info1.observe(this, {
textView.text = it // 更新UI
})
// 完整写法 new Observer onChanged
MyLiveData.info1.observe(this, object: Observer<String> {
override fun onChanged(t: String?) {
textView.text = t // 更新UI
}
})
// 完整写法 new Observer onChanged
MyLiveData.info1.observe(this, object: Observer<String> {
override fun onChanged(t: String?) {
textView.text = t // 更新UI
}
})
// 完整写法 new Observer onChanged
MyLiveData.info1.observe(this, object: Observer<String> {
override fun onChanged(t: String?) {
textView.text = t // 更新UI
}
})
// 完整写法 new Observer onChanged
MyLiveData.info1.observe(this, object: Observer<String> {
override fun onChanged(t: String?) {
textView.text = t // 更新UI
}
})
// 2 触发数据改变 环节
MyLiveData.info1.value = "default" // setValue 主线程
thread {
Thread.sleep(3000)
MyLiveData.info1.postValue("三秒钟后,修改了哦") // postValue 子线程
}
thread {
// 子线程
Thread.sleep(6000)
MyLiveData.info1.postValue("六秒钟后,修改了哦") // postValue 子线程
}
}
}
object MyLiveData {
// 单例
// 懒加载
val info1: MutableLiveData<String> by lazy {
MutableLiveData() }
}
2.模拟后台推送
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
// 启动服务
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
startService(Intent(this, MyService::class.java))
Toast.makeText(MainActivity2@this, "推送服务器启动成功", Toast.LENGTH_SHORT).show()
}
// 一股脑执行,他不会去检测生命周期
// snedMessage(handler)
// 眼睛 观察者 微信列表可见的情况下,才能做事情
MyLiveData.data1.observe(this, {
Log.d("server", "界面可见,说明用户在查看微信列表界面啦,更新消息列表UI界面:${it}")
Toast.makeText(this, "更新消息列表UI界面成功:${it}", Toast.LENGTH_SHORT).show()
})
}
}
object MyLiveData {
// 单例
// 这里为info1的MutableLiveData 懒加载初始化(懒加载:用到时才加载)
val data1 : MutableLiveData<String> by lazy {
MutableLiveData() }
init {
// data1.value = "default" // 违背在 子线程 setValue
data1.postValue("DDD") // 子线程 执行 postValue 非常OK
}
}
// 模拟后台推送
class MyService : Service() {
override fun onBind(intent: Intent): IBinder ? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
thread {
for (x in 1..100000) {
Log.d("server", "服务器给推你推送消息啦(叮咚声响),消息内容是:${x}")
MyLiveData.data1.postValue("服务器给推你推送消息啦,消息内容是:${x}")
Thread.sleep(2000) // 5秒钟推一次
}
}
return super.onStartCommand(intent, flags, startId)
}
}
3.数据粘性
class MainActivity3 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main3)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
// version++ == 0 第一步
MyLiveData.value1.value = "我就是我,不一样的烟火1" // 以前的旧数据
MyLiveData.value1.value = "我就是我,不一样的烟火2" // 以前的旧数据
MyLiveData.value1.value = "我就是我,不一样的烟火3" // 以前的旧数据
MyLiveData.value1.value = "我就是我,不一样的烟火4" // 以前的旧数据
MyLiveData.value1.value = "我就是我,不一样的烟火5" // 以前的旧数据
startActivity(Intent(this, MainActivity4::class.java))
}
}
}
// this@MainActivity4 每个类都有符号
class MainActivity4 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main4)
// 我后观察数据,居然能够收到 前面修改的数据,这就是 数据黏性
/*MyLiveData.value1.observe(this, { Toast.makeText(this, "观察者数据变化:$it", Toast.LENGTH_SHORT).show() })*/
// 第二步
MyLiveData.value1.observe(this, object: Observer<String>{
override fun onChanged(t: String?) {
Toast.makeText(this@MainActivity4, "观察者数据变化$t", Toast.LENGTH_SHORT).show()
}
})
/*// 此观察者 和 handler没有区别,一股脑的执行 (极端的情况,可以用) // 手动考虑释放工作 MyLiveData.value1.observeForever({ }) // // 关心的新数据 MyLiveData.value1.postValue("1111") // // 关心的新数据 MyLiveData.value1.postValue("1111") // // 关心的新数据 MyLiveData.value1.postValue("1111") // // 关心的新数据 MyLiveData.value1.postValue("1111") // 先订阅 ok(object : Callback { override fun show() { } })*/
}
fun ok(callback: Callback) {
// 后触发
callback.show()
}
override fun onStart() {
super.onStart()
}
override fun onDestroy() {
super.onDestroy()
// 手动释放
// MyLiveData.value1.removeObserver()
}
}
object MyLiveData {
// 这里为info1的MutableLiveData 懒加载初始化(懒加载:用到时才加载)
val value1 : MutableLiveData<String> by lazy {
MutableLiveData() }
}
3.Livedata源码解析
下面来看observe方法做了哪些操作,observe方法的主要代码如下:
/** * Adds the given observer to the observers list within the lifespan of the given * owner. The events are dispatched on the main thread. If LiveData already has data * set, it will be delivered to the observer. * <p> * The observer will only receive events if the owner is in {@link Lifecycle.State#STARTED} * or {@link Lifecycle.State#RESUMED} state (active). * <p> * If the owner moves to the {@link Lifecycle.State#DESTROYED} state, the observer will * automatically be removed. * <p> * When data changes while the {@code owner} is not active, it will not receive any updates. * If it becomes active again, it will receive the last available data automatically. * <p> * LiveData keeps a strong reference to the observer and the owner as long as the * given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to * the observer & the owner. * <p> * If the given owner is already in {@link Lifecycle.State#DESTROYED} state, LiveData * ignores the call. * <p> * If the given owner, observer tuple is already in the list, the call is ignored. * If the observer is already in the list with another owner, LiveData throws an * {@link IllegalArgumentException}. * * @param owner The LifecycleOwner which controls the observer * @param observer The observer that will receive the events */
@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方法首先会通过assertMainThread方法检查程序当前是否运行在主线程中,如果不是,则抛出一个异常。使用时需要确保observe方法是执行在主线程中的,且LiveData和生命周期相关联,如果当前状态是非活跃状态则不会执行。这里提一下,如果想让数据监测变化不受活动状态的影响,可以使用observeForever方法,这样Activity即使不处于活动状态,也可以接收到改变的数据,但当Activity销毁时,一定要主动调用removeObserver方法,否则LiveData会一直存在,这会导致内存泄漏。
activity中的addObserver传进来的只是一个接口,在这个接口上进行进一步封装为
LifecycleBoundObserver,保存了宿主的lifecycleowner;shouldBeActive() 是为了判断宿主是否为活跃状态。
/** * A simple callback that can receive from {@link LiveData}. * * @param <T> The type of the parameter * * @see LiveData LiveData - for a usage description. */
public interface Observer<T> {
/** * Called when the data is changed. * @param t The new data */
void onChanged(T t);
}
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() {
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);
}
}
LifecycleBoundObserver实现了LifecycleEventObserver接口,当页面发生改变的时候,程序会走到onStateChanged方法中。从上述源码可以看出,当页面被销毁时会调用removeObserver移除观察,所以使用LiveData的observe方法不用担心存在内存泄漏的风险。如果之前的周期与当前不同,则会同步一次状态,并调用activeStateChanged方法,而activeStateChanged方法则会调用dispatchingValue方法分发数据。dispatchingValue方法的代码如下:
@SuppressWarnings("WeakerAccess") /* synthetic access */
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;
}
这里通过使用mDispatchingValue变量标记来防止分发相同的内容,通过循环方式遍历所有的观察者,通过considerNotify方法更新数据。为的是时时刻刻读取lifecycle生命周期,获取到最新的生命周期状态:
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的onChanged方法中,从而实现在UI层接收数据的回调。那么这个版本号什么时候会更新呢?来看设置数据的方法,这里以setValue方法为例,代码如下:
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
可以看到,当调用setValue方法时,数据版本号会改变,并且会通过dispatching-Value方法进行数据处理,这样就实现了LiveData可观察的特性。
对于postvalue而言:
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);
}
}
利用handler将线程切换到主线程
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
@Override
public void postToMainThread(Runnable runnable) {
mDelegate.postToMainThread(runnable);
}
接下来我们看runnable的代码,本质上也是调用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);
}
};
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
文章评论