一、LiveData的基本使用
LiveData添加一个观察者时,会关联一个LifecycleOwner,然后把这个观察者(observer)与 owner包装成一个LifecycleBoundObserver,和LifecycleOwner的getLifecycle关联,当LifecycleBoundObserver的生命周期变化时,会调用LifecycleBoundObserver的onStateChange()方法,在这个方法中判断当前生命周期和上次的生命周期是否是同一类型(要么活跃,要么非活跃),如果是就之间返回,避免重复通知(start通知了,resume就不再需要通知了),如果不是同一类型,并且当前生命周期是活跃状态,就调用dispatchingValue()方法通知观察者,判断LifecycleOwner是否活跃状态,如果是,将LiveData中持有的最新数据更新给观察者。
1. 使用方式一
MyLiveData.kt
package com.example.mylivedata.simple1
import androidx.lifecycle.MutableLiveData
object MyLiveData { // 单例
// 懒加载
val info : MutableLiveData<String> by lazy { MutableLiveData<String>() }
}
MainActivity.kt
package com.example.mylivedata.simple1
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import androidx.lifecycle.Observer
import com.example.mylivedata.R
import kotlin.concurrent.thread
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView : TextView = findViewById(R.id.tv_textView)
// TODO 1.观察者 环节
MyLiveData.info.observe(this, Observer<String> { t ->
textView.text = t // 更新UI
})
// 完整写法 new Observer 重写onChange方法
MyLiveData.info.observe(this, object : Observer<String> {
override fun onChanged(t: String?) {
textView.text = t // 更新UI
}
})
// TODO 2.触发数据改变 环节
MyLiveData.info.value = "default" // setValue 主线程
thread {
Thread.sleep(3000)
MyLiveData.info.postValue("三秒钟后,修改了哦") // postValue 子线程
}
thread {
Thread.sleep(6000)
MyLiveData.info.postValue("六秒钟后,修改了哦") // postValue 子线程
}
}
}
2. 使用方式二
MyLiveData.kt
package com.example.mylivedata.simple2
import androidx.lifecycle.MutableLiveData
object MyLiveData { // 单例
// 这里为data的MutableLiveData 懒加载初始化(懒加载:用到时才加载)
val data : MutableLiveData<String> by lazy { MutableLiveData<String>()}
init {
// data.value = "dafault" // 违背 在子线程setValue(SetValue在主线程中执行)
data.postValue("test") // 子线程 执行postValue(postValue在子线程中执行)
}
}
MyServer.kt
package com.example.mylivedata.simple2
import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Log
import kotlin.concurrent.thread
// 模拟后台推送
class MyServer : Service() {
override fun onBind(intent: Intent?): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
thread {
for ( x in 1 .. 1000) {
Log.d("MyServer", "服务器给你推送消息(叮咚声响),消息内容是:${x}")
MyLiveData.data.postValue("服务器给你推送消息啦,消息内容是:${x}")
Thread.sleep(2000) // 2秒推送一次
}
}
return super.onStartCommand(intent, flags, startId)
}
}
MainActivity2.kt
package com.example.mylivedata.simple2
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.mylivedata.R
import java.util.*
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
// 启动服务
val button = findViewById<Button>(R.id.bt)
button.setOnClickListener {
startService(Intent(this, MyServer::class.java))
Toast.makeText(this, "推送服务器启动成功", Toast.LENGTH_SHORT).show()
}
// 观察者 界面可见的情况下,才能做事情
MyLiveData.data.observe(this, androidx.lifecycle.Observer {
Log.d("MyServer", "界面可见,说明用户在查看列表界面啦,更新信息列表UI界面:${it}")
Toast.makeText(this, "更新消息列表UI界面成功:${it}", Toast.LENGTH_SHORT).show()
})
}
}
3. 使用方式三
该方式使用的是黏性数据
MyLiveData.kt
package com.example.mylivedata.simple3
import androidx.lifecycle.MutableLiveData
object MyLiveData {
// 这里的data的MutableLiveData 懒加载初始化(懒加载:用到时才加载)
val data : MutableLiveData<String> by lazy { MutableLiveData<String>() }
}
MainActivity3.kt
package com.example.mylivedata.simple3
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.example.mylivedata.R
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 {
MyLiveData.data.value = "我就是我,不一样的烟火"
startActivity(Intent(this, MainActivity4::class.java))
}
}
}
MainActivity4.kt
package com.example.mylivedata.simple3
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import com.example.mylivedata.R
class MainActivity4 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main4)
// 后观察数据,居然能够收到 前面修改的数据,这就是 数据黏性
/*
MyLiveData.data.observe(this, Observer {
Toast.makeText(this, "观察者数据变化:${it}", Toast.LENGTH_SHORT).show()
})
*/
MyLiveData.data.observe(this, object : Observer<String> {
override fun onChanged(t: String?) {
Toast.makeText(this@MainActivity4, "观察者数据变化:$t", Toast.LENGTH_SHORT).show()
}
})
// 此观察者 和handler没有区别,一股脑的执行(极端的情况,可以用)
// 但是需要手动考虑释放工作
//MyLiveData.data.observeForever { }
}
override fun onDestroy() {
super.onDestroy()
// 手动释放
//MyLiveData.data.removeObserver()
}
}
二、LiveData 去除黏性数据的方法
1. 去除黏性的Java版本
OkLiveDataBusJava.java
package com.example.mylivedata.simple4;
import androidx.annotation.NonNull;
import androidx.arch.core.internal.SafeIterableMap;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* 单例模式 去掉粘性事件 Java版本
*/
public class OkLiveDataBusJava {
// 存放订阅者
private Map<String, BusMutableLiveData<Object>> bus;
private static OkLiveDataBusJava liveDataBus = new OkLiveDataBusJava();
private OkLiveDataBusJava() {
bus = new HashMap<>();
}
public static OkLiveDataBusJava getInstance() {
return liveDataBus;
}
// 注册订阅者
public synchronized <T> BusMutableLiveData<T> with(String key, Class<T> type) {
if (bus.containsKey(key)) {
bus.put(key, new BusMutableLiveData<>());
}
return (BusMutableLiveData<T>) bus.get(key);
}
public static class BusMutableLiveData<T> extends MutableLiveData<T> {
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
super.observe(owner, observer); // 启用系统的功能,不写就破坏了
hook(observer);
}
private void hook(Observer<? super T> observer) {
try {
// TODO 1.得到mLastVersion
// 获取到LiveData类中的mObservers对象
Class<LiveData> liveDataClass = LiveData.class;
Field mObserversField = liveDataClass.getDeclaredField("mObservers");
mObserversField.setAccessible(true);
// 获取到这个成员变量的对象
Object mObserversObject = mObserversField.get(this);
// 得到map对象的class对象 private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
Class<?> mObserversClass = mObserversObject.getClass();
// 获取到mObservers对象的get方法
Method get = mObserversClass.getDeclaredMethod("get", Object.class);
get.setAccessible(true);
// 执行get方法
Object invokeEntry = get.invoke(mObserversObject, observer);
// 取到entry中的value
Object observerWrapper = null;
if (invokeEntry != null && invokeEntry instanceof Map.Entry) {
observerWrapper = ((Map.Entry) invokeEntry).getValue();
}
if (observerWrapper == null) {
throw new NullPointerException("observerWrapper is null");
}
// 得到observerWrapper的类对象
// observerWrapper.getClass() 获取的是LifecycleBoundObserver类对象
// observerWrapper类是LifecycleBoundObserver类的父类
Class<?> supperClass = observerWrapper.getClass().getSuperclass();
Field mLastVersion = supperClass.getDeclaredField("mLastVersion");
mLastVersion.setAccessible(true);
// TODO 2.得到mVersion
Field mVersion = liveDataClass.getDeclaredField("mVersion");
mVersion.setAccessible(true);
// TODO 3.mLastVersion = mVersion
Object mVersionValue = mVersion.get(this);
mLastVersion.set(observerWrapper, mVersionValue);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
2. 去除黏性的Kotlin版本
OKLiveDataBusKT.kt
package com.example.mylivedata.simple4
import android.util.Log
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import java.lang.NullPointerException
import java.lang.reflect.Field
import java.lang.reflect.Method
/**
* 单例模式 去掉黏性事件(有关闭黏性的开关)KT版本
*/
object OKLiveDataBusKT {
// 存放订阅者
private val bus : MutableMap<String, BusMutableLiveData<Any>> by lazy { HashMap<String, BusMutableLiveData<Any>>() }
// 暴露一个函数,给外界注册,订阅者关系
fun <T> with(key : String, type : Class<T>, isStack : Boolean = true) : BusMutableLiveData<T> {
if (!bus.containsKey(key)) {
bus[key] = BusMutableLiveData(isStack)
}
return bus[key] as BusMutableLiveData<T>
}
class BusMutableLiveData<T> private constructor() : MutableLiveData<T>() {
var isStack : Boolean = false
// 次构造
constructor(isStack: Boolean) : this() {
this.isStack = isStack
}
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
super.observe(owner, observer)
if (!isStack) {
hook(observer)
Log.d("abc", "Kotlin版本 不启用黏性")
} else {
Log.d("abc", "Kotlin版本 启用黏性")
}
}
private fun hook(observer: Observer<in T>) {
// TODO 1.得到mLastVersion
// 获取到LiveData的类中的mObservers对象
val liveDataClass = LiveData::class.java
val mObserversField = liveDataClass.getDeclaredField("mObservers")
mObserversField.isAccessible = true // 私有修饰可以访问
// 获取到这个成员变量的对象 Kotlin Any == Java Object
val mObserversObject : Any = mObserversField.get(this)
// 得到map对象的class对象 private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
val mObserversClass : Class<*> = mObserversObject.javaClass
// 获取到mObservers对象的get方法, protected Entry<K, V> get(K k)
val get : Method = mObserversClass.getDeclaredMethod("get", Any::class.java)
get.isAccessible = true // 私有修饰也可以访问
// 执行get方法
val invokeEntry : Any = get.invoke(mObserversObject, observer)
// 取到entry中的value
var observerWrapper : Any? = null
if (invokeEntry != null && invokeEntry is Map.Entry<*, *>) {
observerWrapper = invokeEntry.value
}
if (observerWrapper == null) {
throw NullPointerException("observerWrapper is null")
}
// 得到observerWrapper的类对象
val supperClass : Class<*> = observerWrapper.javaClass.superclass
val mLastVersion : Field = supperClass.getDeclaredField("mLastVersion")
mLastVersion.isAccessible = true
// TODO 2.得到mVersion
val mVersion : Field = liveDataClass.getDeclaredField("mVersion")
mVersion.isAccessible = true
// TODO 3.mLastVersion = mVersion
val mVersionValue = mVersion.get(this)
mLastVersion.set(observerWrapper, mVersionValue)
}
}
}
MainActivity.kt文章来源:https://www.toymoban.com/news/detail-671416.html
package com.example.mylivedata.simple4
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.example.mylivedata.R
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// LiveData发生消息通知所有的观察者数据变化了
// KT版本 旧数据 黏性数据
OKLiveDataBusKT.with("data1", String::class.java).value = "liveData kotlin数据"
// Java版本
OkLiveDataBusJava.getInstance().with("data2", String::class.java).value = "livaData java数据"
// 点击事件,跳转到下一个Activity
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
startActivity(Intent(this, MainActivity2::class.java))
}
}
}
MainActivity2.kt文章来源地址https://www.toymoban.com/news/detail-671416.html
package com.example.mylivedata.simple4
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import com.example.mylivedata.R
import kotlin.concurrent.thread
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
// Kotlin版本订阅观察者
OKLiveDataBusKT.with("data1", String::class.java).observe(this, Observer(){
Toast.makeText(this, "Kotlin版本的观察者:${it}", Toast.LENGTH_SHORT).show()
Log.d("abc", "Kotlin版本的观察者:${it}")
})
// Java版本订阅观察者(Java是模拟剔除黏性的)
OkLiveDataBusJava.getInstance().with("data2", String::class.java).observe(this, Observer() {
Toast.makeText(this, "Java版本的观察者:${it}", Toast.LENGTH_SHORT).show()
Log.d("abc", "Java版本的观察者:${it}")
})
thread {
Thread.sleep(2000)
OKLiveDataBusKT.with("data1", String::class.java).postValue("2222")
}
thread {
Thread.sleep(4000)
OkLiveDataBusJava.getInstance().with("data2", String::class.java).postValue("4444")
}
}
}
到了这里,关于LiveData相关基本使用及去除黏性数据的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!