LiveData使用
1.在Activity 中 通过 ViewModelProvider(this).get(XxxViewModel::class.java) 获取到XxxViewModel对象
2.通过XxxViewModel对象获取到定义在XxxViewModel中的liveData
3.通过liveData的observe方法 监测数据发生改变回调弹出吐丝
4.通过按钮点击事件模拟数据发生改变
代码如下:
//Activity中代码
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
observeLiveData()
}
fun onClick(v: View) {
when (v.id) {
//通过按钮点击事件模拟数据发生改变
R.id.btn_00 -> {
var viewModel = ViewModelProvider(this).get(MusicViewModel::class.java)
viewModel.changeItem(0,"009")
}
}
}
fun observeLiveData(){
var viewModel = ViewModelProvider(this).get(MusicViewModel::class.java)
viewModel.musics.observe(this, Observer<List<String>>() { str ->
//数据发生改变 弹出吐司
Toast.makeText(this, str.toString(), Toast.LENGTH_SHORT).show()
})
}
public class MusicViewModel extends ViewModel {
// 定义一个对象,相当于用来存放数据的仓库
private static MutableLiveData<List<String>> liveData;
/**
* 用于获取数据
* 并保存到LiveData中(可以理解成数据仓库)
*/
public MutableLiveData<List<String>> getMusics() {
if (liveData == null) {
List<String> musics = loadMusics();
liveData = new MutableLiveData<>();
//liveData.setValue(musics);
// 把数据存放到仓库
// post 和 set 是跟同步异步区别
liveData.postValue(musics);
}
return liveData;
}
/**
* 加载数据
* 可以从本地或者通过服务端请求获得
*/
private List<String> loadMusics() {
List<String> musics = new ArrayList<>();
musics.add("001");
musics.add("002");
musics.add("003");
return musics;
}
/**
* 修改某条数据
*/
public void changeItem(int index, String music) {
List<String> musics = liveData.getValue();
musics.set(index, music);
liveData.postValue(musics);
}
}
LiveData简单封装成LiveDataBus实现EventBus发布订阅式效果:
LiveDataBus
public class LiveDataBus {
private static LiveDataBus instance;
private Map<String, MutableLiveData> bus;
public static LiveDataBus getInstance() {
if (instance == null) {
synchronized (LiveDataBus.class) {
if (instance == null) {
instance = new LiveDataBus();
}
}
}
return instance;
}
private LiveDataBus() {
bus = new ConcurrentHashMap<>();
}
public synchronized <T> MutableLiveData<T> with(String key, Class<T> type) {
if (!bus.containsKey(key)) {
bus.put(key, new MutableLiveData<>());
}
// 如果不需要阻止黏性事件,则换回MutableLiveData
return (MutableLiveData<T>) bus.get(key);
}
}
在Activity中使用LiveDataBus:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
registerLiveDataBus()
}
fun registerLiveDataBus(){
//这里我们注册一个test01事件 参数类型是String
LiveDataBus.getInstance().with("test01",String::class.java)
.observe(this, Observer<String>() {str->
Toast.makeText(this, str, Toast.LENGTH_SHORT).show()
})
}
fun onClick(v: View) {
when (v.id) {
//发送事件 上面registerLiveDataBus方法中就会弹出吐司
R.id.btn_00 -> {
LiveDataBus.getInstance().with("test01",String::class.java)
.postValue("001")
}
}
}
解决LiveDataBus黏性事件bug
继承LiveData类替换系统的MutableLiveData 代码如下:
public class MLiveData<T> extends LiveData<T> {
private boolean hasModified = false;
private Handler handler;
// 只有onStart后,对数据的修改才会触发 observer.onChanged()
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer<? super T> observer) {
super.observe(owner, new Observer<T>() {
private boolean hasIntercept = false;
// 创建了一个新的Observer来包装处理我们传入的observer
@Override
public void onChanged(T t) {
// 通过逻辑判断来解决不需要粘性事件的情况
if (!hasModified || hasIntercept) {
observer.onChanged(t);
}
hasIntercept = true;
}
});
}
// 无论何时,只要数据发生改变,就会触发 observer.onChanged()
@Override
public void observeForever(@NonNull final Observer<? super T> observer) {
super.observeForever(new Observer<T>() {
private boolean hasIntercept = false;
@Override
public void onChanged(T t) {
if (!hasModified || hasIntercept) {
observer.onChanged(t);
}
hasIntercept = true;
}
});
}
@Override
public void setValue(T value) {
super.setValue(value);
hasModified = true;
LogUtil.e("MLiveData hasModified=" + hasModified);
}
/**
* 这里可能存在问题?
* 第一次需要使用handler来解决hasModified在异步情况先先改变的问题
*
* @param value
*/
@Override
public void postValue(T value) {
super.postValue(value);
if (handler == null) {
handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
hasModified = true;
}
});
} else {
hasModified = true;
}
// 不能直接修改hasModified值,因为异步情况导致还没onChanged调用就到这里了
// hasModified = true;
}
}