• LiveDataBus的简单使用


    这里简单的介绍LiveDataBus的使用,下面是LiveData的优点:

    LiveData优点

    解释

    UI和十几数据保持一致

    LiveData采用观察者模式,数据发生时获得通知,更新UI

    避免内存泄漏

    观察者绑定到组件的生命周期上,当被绑定的组件销毁(destroy)时,观察者会立刻自动清理自身的数据

    不会因为Activity处于Stop状态时引起奔溃

    当Activity处于后台状态时,不会接受到LiveData的任何事件

    不需要解决生命周期带来的问题

    LiveData可以感知被绑定的组件的生命周期,只有在活跃状态才会通知数据变化

    实时数据刷

    当组件处于活跃状态或者从不活跃状态到活跃状态时总是能收到最新的数据

    解决Configuration Change问题

    在屏幕发生旋转或者被回收再次启动,立刻就能收到最新的数据

    看一下LiveDataBus的整体架构(画的不好看,莫笑):

    接下来看一下LiveDataBus的使用(先看有BUG的),新建一个LiveDataBus1类(这里我直接贴出代码):

     1 public final class LiveDataBus1 {
     2 
     3     private final Map<String, MutableLiveData<Object>> bus;
     4 
     5     private LiveDataBus1() {
     6         bus = new HashMap<>();
     7     }
     8 
     9     private static class SingletonHolder {
    10         private static final LiveDataBus1 DATA_BUS = new LiveDataBus1();
    11     }
    12 
    13     public static LiveDataBus1 get() {
    14         return SingletonHolder.DATA_BUS;
    15     }
    16 
    17     public <T> MutableLiveData<T> getChannel(String target, Class<T> type) {
    18         if (!bus.containsKey(target)) {
    19             bus.put(target, new MutableLiveData<>());
    20         }
    21         return (MutableLiveData<T>) bus.get(target);
    22     }
    23 
    24     public MutableLiveData<Object> getChannel(String target) {
    25         return getChannel(target, Object.class);
    26     }
    27 }

    然后在MainActivty中使用,用一个按钮发送消息,同时启动一个新界面:

    1 @Override
    2     public void onClick(View view) {
    3         LiveDataBus1.get().getChannel("nice").setValue("Hello Android!");
    4         Intent intent = new Intent(this,TestActivity.class);
    5         startActivity(intent);
    6     }

    在新的界面的onCreate中注册订阅,然后添加一个TextView控件显示接收消息内容:

    1  LiveDataBus1.get().getChannel("nice",String.class).observe(this, new Observer<String>() {
    2             @Override
    3             public void onChanged(String s) {
    4                 txtTest.setText(s);
    5             }
    6         });

    启动项目,点击按钮,跳到新界面后发现TextView控件立马就显示内容了,这不是想要的结果。


    第2种效果,新建一个LiveDataBus类,我直接贴出代码:

      1 public class LiveDataBus {
      2 
      3     private final Map<String,BusMutableLiveData<Object>> bus;
      4 
      5     private LiveDataBus(){
      6         bus = new HashMap<>();
      7     }
      8 
      9     private static class SingletonHolder{
     10         private static final LiveDataBus DEFAULT_BUS = new LiveDataBus();
     11     }
     12 
     13     public static LiveDataBus get(){
     14         return SingletonHolder.DEFAULT_BUS;
     15     }
     16 
     17     public <T> MutableLiveData<T> with(String key,Class<T> type){
     18         if(!bus.containsKey(key)) {
     19             bus.put(key, new BusMutableLiveData<>());
     20         }
     21         return (MutableLiveData<T>) bus.get(key);
     22     }
     23 
     24     public MutableLiveData<Object> with(String key){
     25         return with(key,Object.class);
     26     }
     27 
     28     private static class ObserverWrapper<T> implements androidx.lifecycle.Observer<T> {
     29 
     30         private androidx.lifecycle.Observer<T> observer;
     31 
     32         public ObserverWrapper(Observer<T> observer) {
     33             this.observer = observer;
     34         }
     35 
     36         @Override
     37         public void onChanged(@Nullable T t) {
     38             if (observer != null) {
     39                 if (isCallOnObserve()) {
     40                     return;
     41                 }
     42                 observer.onChanged(t);
     43             }
     44         }
     45 
     46         private boolean isCallOnObserve() {
     47             StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
     48             if (stackTrace != null && stackTrace.length > 0) {
     49                 for (StackTraceElement element : stackTrace) {
     50                     if ("android.arch.lifecycle.LiveData".equals(element.getClassName()) &&
     51                             "observeForever".equals(element.getMethodName())) {
     52                         return true;
     53                     }
     54                 }
     55             }
     56             return false;
     57         }
     58     }
     59 
     60     private static class BusMutableLiveData<T> extends MutableLiveData<T> {
     61 
     62         private Map<Observer, Observer> observerMap = new HashMap<>();
     63 
     64         @Override
     65         public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
     66             super.observe(owner, observer);
     67             try {
     68                 hook(observer);
     69             } catch (Exception e) {
     70                 e.printStackTrace();
     71             }
     72         }
     73 
     74         @Override
     75         public void observeForever(@NonNull Observer<? super T> observer) {
     76             if (!observerMap.containsKey(observer)) {
     77                 observerMap.put(observer, new ObserverWrapper(observer));
     78             }
     79             super.observeForever(observerMap.get(observer));
     80         }
     81 
     82         @Override
     83         public void removeObserver(@NonNull Observer<? super T> observer) {
     84             Observer realObserver = null;
     85             if (observerMap.containsKey(observer)) {
     86                 realObserver = observerMap.remove(observer);
     87             } else {
     88                 realObserver = observer;
     89             }
     90             super.removeObserver(realObserver);
     91         }
     92 
     93         private void hook(@NonNull Observer<? super T> observer) throws Exception {
     94             //get wrapper's version
     95             Class<LiveData> classLiveData = LiveData.class;
     96             Field fieldObservers = classLiveData.getDeclaredField("mObservers");
     97             fieldObservers.setAccessible(true);
     98             Object objectObservers = fieldObservers.get(this);
     99             Class<?> classObservers = objectObservers.getClass();
    100             Method methodGet = classObservers.getDeclaredMethod("get", Object.class);
    101             methodGet.setAccessible(true);
    102             Object objectWrapperEntry = methodGet.invoke(objectObservers, observer);
    103             Object objectWrapper = null;
    104             if (objectWrapperEntry instanceof Map.Entry) {
    105                 objectWrapper = ((Map.Entry) objectWrapperEntry).getValue();
    106             }
    107             if (objectWrapper == null) {
    108                 throw new NullPointerException("Wrapper can not be bull!");
    109             }
    110             Class<?> classObserverWrapper = objectWrapper.getClass().getSuperclass();
    111             Field fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion");
    112             fieldLastVersion.setAccessible(true);
    113             //get livedata's version
    114             Field fieldVersion = classLiveData.getDeclaredField("mVersion");
    115             fieldVersion.setAccessible(true);
    116             Object objectVersion = fieldVersion.get(this);
    117             //set wrapper's version
    118             fieldLastVersion.set(objectWrapper, objectVersion);
    119         }
    120     }
    121 }

    同样是在MainAct按钮中发送消息,跳转到新页面,这里我就直贴出发送消息的代码:
     1 LiveDataBus.get().with("test").setValue("Hello Android!"); 

    然后在新新界面中添加一个Button控件,然后先把注册订阅放在Button的点击事件中:

    1 LiveDataBus.get().with("test",String.class).observe(this, new Observer<String>() {
    2             @Override
    3             public void onChanged(String s) {
    4                 txtTest.setText(s);
    5             }
    6         });
    7     }

    做完以上操作后,点击MainActivity的Button跳到新界面,再然后点击新界面的Button控件,TextView控件的值就改变了,LiveDataBus的简单使用就说到这里了。

  • 相关阅读:
    实操记录之-----Ant Design of Vue 增强版动态合并单元格,自动根据数据进行合并,可自定义横纵向合并
    实操好用~~~~~antd 中 Table表格动态合并~~~
    超级容易理解的函数节流(throttle)
    Flask框架
    Celery框架
    redis数据库如何用Django框架缓存数据
    luffyapi项目 --短信认证的基本操作
    DRF之Jwt 实现自定义和DRF小组件及django-filter插件的使用
    Auth主件的(RBAC) 六表
    DRF之三大认证
  • 原文地址:https://www.cnblogs.com/Mr-Deng/p/11647009.html
Copyright © 2020-2023  润新知