zoukankan      html  css  js  c++  java
  • Android开发 SingleLiveEvent解决LiveData或者MutableLiveData多次回调的问题

    前言

      只要使用过一段时间的LiveData就会发现,LiveData会经常多次回调数据。我们经常碰到的这个问题。

    问题复现

        我们的ViewModel里是给Activity持有的并且里面有一个LiveData数据,我们A_Fragment现在获得Activity的ViewModel并且注册LiveData数据成为观察者,这个时候我们setValue()就会让前台的A_Fragment得到一次LiveData数据,接下来操作 A_Fragment 启动 B_Fragment,在返回到A_Fragment。 你会发现只要再次注册LiveData的observe(this, new Observer ...),那么A_Fragment里面又会接收到一次LiveData的数据。

    为什么会这样呢?

      1.一部分原因是LiveData的机制,就是向所有前台Fragment或者Activity发送数据。只要注册的观察者在前台就必定会收到这个数据。

      2.另一部分的原因是对ViewModel理解不深刻,理论上只有在Activity保存的ViewModel它没被销毁过就会一直给新的前台Fragment观察者发送数据。我们需要管理好ViewModel的使用范围。 比如只需要在Fragment里使用的ViewModel就不要给Activity保管。而根Activity的ViewModel只需要做一下数据共享与看情况使用LiveData。

    解决问题

    第一种方法

    就是管理好ViewModel的范围,如果业务范围只跟某个Fragment有关,那么最好就只给这个Fragment使用。这样Fragment在销毁或者创建的时候,也会销毁ViewModel与创建ViewModel,ViewModel携带的LiveData就是全新的不会在发送之前设置的数据。

    第二种方法

    就是使用一个google大神实现的一个复写类 SingleLiveEvent,其中的机制是用一个原子 AtomicBoolean记录一次setValue。在发送一次后在将AtomicBoolean设置为false,阻止后续前台重新触发时的数据发送。

    import androidx.annotation.MainThread;
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.lifecycle.LifecycleOwner;
    import androidx.lifecycle.MutableLiveData;
    import androidx.lifecycle.Observer;
    
    import java.util.concurrent.atomic.AtomicBoolean;
    
    public class SingleLiveEvent<T> extends MutableLiveData<T> {
        private final AtomicBoolean mPending = new AtomicBoolean(false);
        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer<? super T> observer) {
            super.observe(owner, new Observer<T>() {
                @Override
                public void onChanged(@Nullable T t) {
                    if (mPending.compareAndSet(true, false)) {
                        observer.onChanged(t);
                    }
                }
            });
        }
    
        @MainThread
        public void setValue(@Nullable T t) {
            mPending.set(true);
            super.setValue(t);
        }
    
        /**
         * Used for cases where T is Void, to make calls cleaner.
         */
        @MainThread
        public void call() {
            setValue(null);
        }
    }
  • 相关阅读:
    js日历,使用datepicker.js,ui.core.js,jquery-1.7.1.js
    android设置按钮按下的不同效果图
    a标签阻止跳转的方法
    获取浏览器中选中部分,比如文本等
    Android Studio does not point to a valid jvm
    Drawerlayout
    webviewactivity
    ViewFilpper
    Physik
    Betriebssystem
  • 原文地址:https://www.cnblogs.com/guanxinjing/p/12669506.html
Copyright © 2011-2022 走看看