• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Jetpack架构组件 四-- LiveData使用和原理

武飞扬头像
lishutong1006
帮助1

前言

在 LiveData 出现之前,一般状态分发我们使用EventBus或者RxJava,这些都很容易出现内存泄漏问题,而且需要我们手动管理生命周期。而 LiveData 则规避了这些问题,LiveData 是一个持有 Activity、Fragment 生命周期的数据容器。当数据源发生变化的时候,通知它的观察者更新 UI 界面。同时它可以只通知处于 Active 状态的观察者更新界面。所以不用担心内存泄漏问题。一般来说,LiveData很少单独使用,它更多的和Android Jetpack的其他组件搭配使用,比如和ViewModel。这篇文章就来介绍LiveData的使用。

1、 什么是LiveData

LiveData 是一个可观察的数据持有者,和常规的observable不同,LiveData 是可以感知生命周期的,也就是说它能够在 Activity、Fragment、Service 中正确的处理生命周期。

LiveData 的数据源一般是 ViewModel,也可以是其它可以更新 LiveData 的组件。当数据更新后,LiveData 就会通知它的所有观察者,比如 Activity。与 RxJava 的方法不同的是,LiveData 可以不通知所有观察者,它可以只通知处于 Active 状态的观察者。这对于Activity 和 Service 特别有用,因为它们可以安全地观察 LiveData 对象而不用担心内存泄漏的问题。还有一点需要注意的是一旦观察者重新恢复到活跃状态,它将会重新收到 LiveData 的最新数据。

2、 LiveData的基本使用

LiveData 是一个抽象类,它的最简单的实现类为 MutableLiveData,使用方法如下所示:

public class MainActivity extends AppCompatActivity {
    MutableLiveData<String> mutableLiveData  = new MutableLiveData<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mutableLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String s) {
                Log.d("MainActivity", "onChanged:" s);
            }
        });
        mutableLiveData.postValue("LiveData 基本使用");

    }
}
学新通

MutableLiveData 的 observe 方法有两个参数分别是 LifecycleOwner 和 Observer<T> ,第一个参数就是MainActivity 本身,第二个参数新建了一个Observer<String>,在onChanged方法中得到回调。postValue 方法会在主线程中更新数据,运行结果如下所示:

学新通

除了 MutableLiveData 的 postValue 方法,还可以使用 setValue 方法,它们之前的区别是,setValue 方法必须在主线程使用,如果是在子线程线程中更新 LiveData,则可以使用 postValue 方法。

3、 更改LiveData中的数据

如果我们想要在 LiveData 对象分发给观察者之前对其中存储的值进行更改,可以使用 Transformations.map() 和Transformations.switchMap(),下面通过简单的例子来讲解它们。

2.1 Transformations.map()

如果想要在 LiveData 对象分发给观察者之前对其中存储的值进行更改,可以使用Transformations.map()。

public class MainActivity extends AppCompatActivity {
    MutableLiveData<String> mutableLiveData  = new MutableLiveData<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mutableLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String s) {
                Log.d("MainActivity", "onChanged:" s);
            }
        });
        LiveData transformedLiveData = Transformations.map(mutableLiveData, new Function<String, Object>() {
            @Override
            public Object apply(String name) {
                return name   "   Transformations.map 的使用";
            }
        });
        transformedLiveData.observe(this, new Observer() {
            @Override
            public void onChanged(@Nullable Object o) {
                Log.d("MainActivity", "onChanged2:" o.toString());
            }
        });
        mutableLiveData.postValue("LiveData 基本使用");
    }
}
学新通

通过Transformations.map(),在mutableLiveData的基础上又加上了字符串" Transformations.map 的使用"。

运行结果如下所示:

学新通

2.2 Transformations.switchMap()

public class MainActivity extends AppCompatActivity {
    private MutableLiveData<String> mutableLiveData1;
    private MutableLiveData<String> mutableLiveData2;
    private MutableLiveData<Boolean> liveDataSwitch;
    private LiveData transformedLiveData;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mutableLiveData1 = new MutableLiveData<>();
        mutableLiveData2 = new MutableLiveData<>();
        liveDataSwitch = new MutableLiveData<>();

         transformedLiveData= Transformations.switchMap(liveDataSwitch, new Function<Boolean, LiveData<String>>() {
            @Override
            public LiveData<String> apply(Boolean input) {
                if (input) {
                    return mutableLiveData1;
                } else {
                    return mutableLiveData2;
                }
            }
        });

        transformedLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String s) {
                Log.d("MainActivity", "onChanged:"   s);
            }
        });
        liveDataSwitch.postValue(false);
        mutableLiveData1.postValue("Transformations.switchMap 用法1");
        mutableLiveData2.postValue("Transformations.switchMap 用法2");
    }
}
学新通

MutableLiveData<Boolean>()用来控制切换,当 liveDataSwitch 的值为true时返回mutableLiveData1,否则返回 mutableLiveData2。

2.3 合并多个LiveData数据源

MediatorLiveData 继承自 mutableLiveData,它可以将多个 LiveData 数据源集合起来,可以达到一个组件监听多个 LiveData 数据变化的目的,用法如下所示:

public class MainActivity extends AppCompatActivity {
    private MutableLiveData<String> mutableLiveData1;
    private MutableLiveData<String> mutableLiveData2;
    private MediatorLiveData mediatorLiveData;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mutableLiveData1 = new MutableLiveData<>();
        mutableLiveData2 = new MutableLiveData<>();
        mediatorLiveData = new MediatorLiveData<String>();

        mediatorLiveData.addSource(mutableLiveData1, new Observer() {
            @Override
            public void onChanged(@Nullable Object o) {
                Log.d("MainActivity", "onChanged1:"   o.toString());
            }
        });

        mediatorLiveData.addSource(mutableLiveData2, new Observer() {
            @Override
            public void onChanged(@Nullable Object o) {
                Log.d("MainActivity", "onChanged2:"   o.toString());
            }
        });
        mediatorLiveData.observe(this, new Observer() {
            @Override
            public void onChanged(@Nullable Object o) {
                Log.d("MainActivity", "onChanged:"   o.toString());
            }
        });
        mutableLiveData1.postValue("mutableLiveData 1");
        mutableLiveData2.postValue("mutableLiveData 2");
        mediatorLiveData.postValue("mediatorLiveData 使用");
    }
}
学新通

通过 MediatorLiveData 的 addSource 将两个 MutableLiveData 合并到一起,这样当任何一个 MutableLiveData数据发生变化时,MediatorLiveData 都可以感知到,运行结果如下所示:

学新通

4、LiveData源码解析

由于 LiveData 是一个 abstract class,我们不能直接生成他的实例。官方有提供他的实现类MutableLiveData,代码如下所示:

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);
    }
}

创建了 LiveData 后,需要通过 observe 方法或者 observeForever 方法设置一个观察者,这个观察者接口就是Observer,代码如下:

public interface Observer<T> {
    // 这个回调发生在主线程
    void onChanged(T t);
}

LiveData 的添加观察者的代码如下:

public abstract class LiveData<T> {
    ...
    
    //  只有onStart之后,onStop之前,对数据的修改才会触发 observer.onChanged()
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
     }
    
     // 无论何时,只要数据发生改变,就会触发 observer.onChanged()
    public void observeForever(@NonNull Observer<? super T> observer) {
    
    }
 
    ...
}

observeForever 的实现跟 observe 是类似的,这里我们重点看一下 observe()的实现过程,代码如下:

// 只能在主线程调用
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    assertMainThread("observe");
    //如当前UI的状态的是DESTROYED,就不绑定这个回调了
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // ignore
        return;
    }
    //创建生命周期感知的观察者包装类(把注册进来的observer包装成一个具有生命周边边界的观察者)
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    //接着会判断该观察是否已经注册过了,如果是则抛异常, 对应观察者只能与一个owner绑定,不允许重复注册
    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;
    }
    //把wrapper与Activity/Fragment的生命周期,建立关系,
    //当UI的生命周期发生变化的时候,就会去回调wrapper中的onStateChanged方法
    owner.getLifecycle().addObserver(wrapper);
}
学新通

4.2 LifecycleBoundObserver

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    @NonNull
    final LifecycleOwner mOwner;

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
        super(observer);
        mOwner = owner;
    }

    @Override
    boolean shouldBeActive() {
        /*
        观察者是否活跃就等于mOwner的状态是否大于等于STARTED;
        如果页面当前不可见,你发送了一条消息,此时是不会被分发的,
        可以避免后台任务抢占资源,当页面恢复可见才会分发。
        */
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    // Activity/Fragment的生命周期变化会回调此方法。
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
            @NonNull Lifecycle.Event event) {
        Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
        // 如果当接收到DESTROYED的事件会自动解除跟owner的绑定,避免内存泄露
        if (currentState == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        Lifecycle.State prevState = null;
        while (prevState != currentState) {
            prevState = currentState;
            //说明宿主的状态发生了变化,此时会判断宿主是否处于活跃状态
            activeStateChanged(shouldBeActive());
            currentState = mOwner.getLifecycle().getCurrentState();
        }
    }

    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}
学新通

4.3 ObserverWrapper

状态变更后,如果观察者处于活跃状态会触发数据的分发流程

private abstract class ObserverWrapper {
    final Observer<? super T> mObserver;
    boolean mActive;
    //ObserverWrapper在每次注册的时候都会重新new,所以mLastVersion每次都是-1开始。
    int mLastVersion = START_VERSION;

    ObserverWrapper(Observer<? super T> observer) {
        mObserver = observer;
    }

    abstract boolean shouldBeActive();

    boolean isAttachedTo(LifecycleOwner owner) {
        return false;
    }

    void detachObserver() {
    }

    void activeStateChanged(boolean newActive) {
        //当前的生命周期和上一次的生命周期状态,是否发生变化,没有发生变化,就直接返回。
        if (newActive == mActive) {
            return;
        }
        // immediately set active state, so we'd never dispatch anything to inactive
        // owner
        mActive = newActive;
        // 更新活跃值 活跃1 非活跃-1
        changeActiveCounter(mActive ? 1 : -1);
        if (mActive) {
            // 如果是活跃状态,分发值
            dispatchingValue(this);
        }
    }
}
学新通

changeActiveCounter 方法代码如下:

@MainThread
void changeActiveCounter(int change) {
    // 上一次的活跃数
    int previousActiveCount = mActiveCount;
    // 当前活跃数
    mActiveCount  = change;
    if (mChangingActiveState) {
        return;
    }
    mChangingActiveState = true;
    try {
        while (previousActiveCount != mActiveCount) {
           // 从不活跃变为活跃状态,需要回调 onActive方法
            boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
            // 从活跃状态变为不活跃状体,需要回调onInactive方法
            boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
            previousActiveCount = mActiveCount;
            if (needToCallActive) {
                onActive();
            } else if (needToCallInactive) {
                onInactive();
            }
        }
    } finally {
        mChangingActiveState = false;
    }
}
学新通

dispatchingValue(this)数据分发流程控制:(内部执行considerNotify(initiator)方法),这个方法我们后面分析。

4.4 setValue 发送数据源码分析

postValue 最终也是调用 setValue 方法,这里就不做分析了,我们主要分析 setValue 方法,代码如下:

@MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        // 这个mVersion是属于LiveData的,然后只在setValue
        // (postValue最终也会调用setValue)的时候会自增1
        mVersion  ;
        // 保存这次变化的数据
        mData = value;
        // 分发数据
        dispatchingValue(null);
    }

接下来我们具体分析 dispatchingValue 方法,代码如下:

@SuppressWarnings("WeakerAccess") /* synthetic access */
void dispatchingValue(@Nullable ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    //进入while循环前,设置为true,如果此时另外一个数据发生变化,到了此函数中就直接在上面返回了
    mDispatchingValue = true;
    do {
        //开始for循环前,设置为false,for循环完,也会退出while循环
        mDispatchInvalidated = false;
        if (initiator != null) {
        // 如果传递的观察者不为空,则把数据分发给他自己。
        // 这个流程是Activity/Fragment的生命周期发生变化的时候会被触发
            considerNotify(initiator);
            initiator = null;
        } else {
            // 遍历集合中所有已注册的的观察者,逐个调用considerNotify,分发数据
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                //这里mDispatchInvalidated 为true,表示在while循环未结束的时候,
                // 有其他数据发生变化,并调用了该函数
                //在上面的if判断中设置了 mDispatchInvalidated = true,
                // 结束本次for循环,没有退出while循环,开始下一次for循环
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    //退出while 后,设置为false,正常处理数据变化
    mDispatchingValue = false;
}
学新通

这里有两个变量

  • mDispatchingValue 这个变量用来控制,是否进入while 循环,以及while 循环 是否已经结束

  • mDispatchInvalidated 这个变量用来控制for 循环是否要重新开始

看下considerNotify 的函数,调用了之前 LiveData 设置的 observer 的 onChanged 函数,代码如下:

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.
    // 如果当前的生命周期是非活跃,就不回调onChanged函数,
    // 在LifecycleBoundObserver 中记录状态,当生命周期变为活跃,就回去更新数据
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    // 此处判断观察者接收消息的次数是否大于等于 发送消息的次数(observer被创建之初verison=-1 )
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    // 这里会执行传入的observer的onChanged方法
    observer.mObserver.onChanged((T) mData);
}
学新通

综上分析:LiveData的粘性事件

    • 通过同一个LiveData 在更改数据的时候调用 setValue(postValue 最终也会调用 setValue) 的时候内部维护的 mVersion 会自增1,mVersion 初始值是-1

    • 在监听数据变化的时候,即调用 observer 监听的时候,每次内部都会在通过包装类中new ObserverWrapper,内部维护了一个mLastVersion变量,mLastVersion也是初始值为-1,所以注意了,每执行一次 observer 方法内部维护 mLastVersion 都会新创建而变为 -1 ,如果 mLastVersion 小于 mVersion 的时候就表示有新的变化没有回调 observer 的 onChanged 方法。

    • 结论所以只要之前有发射过一次数据,那么后面注册的观察者都会接收到最精一次发射过的数据

这种情况被称为LiveData的粘性事件

扫描下方二维码关注公众号,获取更多技术干货。

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfkceb
系列文章
更多 icon
同类精品
更多 icon
继续加载