拥抱JetPack之LiveData的自我介紹

本文介绍了LiveData,一种Android中的可观察数据存储器,具有生命周期感知功能,确保数据更新仅限于活跃组件。文章详细讲解了LiveData的优势、使用方法,以及其原理,包括setValue和postValue的区别,以及观察者注册和生命周期绑定的过程。
摘要由CSDN通过智能技术生成

大家好,我是LiveData,我是一种可观察的数据存储器类。与常规的可观察类不同,我 具有生命周期感知能力,意指它遵循其他应用组件(如 activity、fragment 或 service)的生命周期。这种感知能力可确保 我 仅更新处于活跃生命周期状态的应用组件观察者。

我不需要像广播那样需要手动解除注册,我可以利用我另一位老伙计的特性  Lifecycle 来实现自动解绑,如果观察者(由 Observer 类表示)的生命周期处于 STARTED 或 RESUMED 状态,则我会认为该观察者处于活跃状态。我只会将更新通知给活跃的观察者。为观察我而注册的非活跃观察者不会收到更改通知。

您可以注册与实现 LifecycleOwner 接口的对象配对的观察者。有了这种关系,当相应的 Lifecycle 对象的状态变为 DESTROYED 时,便可移除此观察者。这对于 activity 和 fragment 特别有用,因为它们可以放心地观察 LiveData 对象,而不必担心泄露(当 activity 和 fragment 的生命周期被销毁时,系统会立即退订它们)。

一、使用LiveData的优势

想必通过上面的介绍,你应该认识我啦~,但是现在也许你有个疑问,就是:我使用你能有什么优势呢?

1.确保界面符合数据状态

我遵循观察者模式。当底层数据发生变化时,我会通知 Observer 对象。您可以整合代码以在这些 Observer 对象中更新界面。这样一来,您无需在每次应用数据发生变化时更新界面,因为观察者会替您完成更新。

2.不会发生内存泄漏

观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。

想了解Lifecycle原理,可以点击我的另一篇文章~

3.不会因 Activity 停止而导致崩溃

如果观察者的生命周期处于非活跃状态(如返回堆栈中的 activity),它便不会接收任何我的事件。

4.不再需要手动处理生命周期

界面组件只是观察相关数据,不会停止或恢复观察。我将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。

5.数据始终保持最新状态

如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。

6.适当的配置更改

如果由于配置更改(如设备旋转)而重新创建了 activity 或 fragment,它会立即接收最新的可用数据。

7.共享资源

您可以使用单例模式扩展我以封装系统服务,以便在应用中共享它们。我连接到系统服务一次,然后需要相应资源的任何观察者只需观察我。如需了解详情,请参阅扩展 LiveData

二、LiveData的使用

了解了我的优势,该教你如何使用我了~

先来介绍下我的使用方法

1.MutableLiveData
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.lifecycle;

/**
 * {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method.
 *
 * @param <T> The type of data hold by this instance
 */
@SuppressWarnings("WeakerAccess")
public class MutableLiveData<T> extends LiveData<T> {

    /**
     * Creates a MutableLiveData initialized with the given {@code value}.
     *
     * @param value initial value
     */
    public MutableLiveData(T value) {
        super(value);
    }

    /**
     * Creates a MutableLiveData with no value assigned to it.
     */
    public MutableLiveData() {
        super();
    }

    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

给大家介绍下,这是我的儿子:MutableLiveData,他重写了我比较重要的两个方法:

setValue(T value) : 设置值,不能在子线程中调用,只可以在主线程调用,不然会crash。

postValue(T value):设置值,可以在子线程中调用。

package com.xcy.mylivedatademo;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class MainViewModel extends ViewModel {

    private MutableLiveData<String> _valueLiveData = new MutableLiveData();
    LiveData<String> valueLiveData = _valueLiveData;

    public void setStringValue(String value) {
        _valueLiveData.postValue(value);
    }
}
2.代码示例

package com.xcy.mylivedatademo;

import android.content.Context;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;

public class MainActivity extends AppCompatActivity {

    private String TAG = MainActivity.class.getSimpleName();
    private MainViewModel viewModel = ViewModelProvider.NewInstanceFactory.getInstance().create(MainViewModel.class);
    private Observer<String> mStrObserveForever;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG,"onCreate");

        //设置值
        viewModel.setStringValue("Hello LiveData~");

        //注册带生命周期的观察者
        viewModel.valueLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String value) {
                Log.d(TAG, "observe ->" + value);
            }
        });

        //注册非生命周期感知的观察者: Activity onStop/onPause 时也能收到值的变化
        mStrObserveForever = new Observer<String>() {
            @Override
            public void onChanged(String value) {
                Log.d(TAG, "observeForever ->" + value);
            }
        };
        viewModel.valueLiveData.observeForever(mStrObserveForever);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG,"onDestroy");
        //非生命周期感知的观察者需要手动解绑,避免内存泄漏
        viewModel.valueLiveData.removeObserver(mStrObserveForever);
    }
}

三、LiveData的原理

了解了如何使用,我觉得你还需要了解一下我的工作原理,这样使用我的时候才能更加的得心应手,不会因为不够了解我,而遇到问题时变得不敢用。

下面让我们从这个问题开始切入:

1.为什么setValue不可以在子线程中调用,而postValue可以?
/**
 * 这是我截取LiveData.java中的部分代码
 */

private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };


    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }

        //没有什么黑科技,只是将Runnable post到主线程中的Handler执行而已,
        //这就是为什么postValue可以在子线程中调用的原因,因为最终这里替你转了下线程,
        //然后去调用setValue() 方法了,仅此而已~
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

    @MainThread
    protected void setValue(T value) {
        //这里会校验当前线程是否为主线程,如果不是则会crash,
        //这就是为什么setValue只能在主线程中调用的原因。
        assertMainThread("setValue");

        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
2.为什么注册监听后,setValue或postValue就可以收到变化通知呢?

解析:根据第一个问题,我们发现setValue中最终会调用到dispatchingValue(null)这个方法,那么让我们沿着这个方法往后看下去吧。

/**
 * 这是我截取LiveData.java中的部分代码
 */

void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                //注意 considerNotify() 这个方法
                considerNotify(initiator);
                initiator = null;
            } else {
                //遍历mObservers中的所有Observer,并且最终调用到 considernotify()
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

解析:目前根据 dispatchingValue() 方法,矛头指向了 considerNotify() 方法,那么让我们看看这个方法干了什么。

/**
 * 这是我截取LiveData.java中的部分代码
 */

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.
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }

        //这里会判断mLastVersion从而判断是否需要回调
        //这个mVersion值会在每次setValue()时++
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;

        //是不是很熟悉呢? 没错~ 这里的onChanged()方法,
        //就是调用我们注册的Observer.onChanged(),
        //然后我们在 setValue() 后就能收到监听啦~
        observer.mObserver.onChanged((T) mData);
    }

解析:至此,你们已经快完全掌握我的原理了,为什么说快完全?因为还有最后一个问题~

3.为什么observe()是注册带生命周期的观察者,而observeForever()是注册非生命周期感知的观察者呢?
/**
 * 这是我截取LiveData.java中的部分代码
 */

@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        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;
        }
        owner.getLifecycle().addObserver(wrapper);
    }


@MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
        assertMainThread("observeForever");
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }

        //记住这里,注册后,直接设置activeStateChanged(true)
        //这个后面会说为什么~
        wrapper.activeStateChanged(true);
    }

解析:看出什么了吗?眼尖的你应该发现了~ 那就是两个方法中的Observer,一个是observer()中的LifecycleBoundObserver ,一个是observeForever()中的 AlwaysActiveObserver ,让我们来看下这两个Observer的实现吧~

/**
 * 这是我截取LiveData.java中与 observer() 相关的部分代码
 */

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

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

        //获取当前的活动状态,如果这个是在Activity中注册的
        //就是判断当前Activity是否处于活跃状态:onCreate,onResume,onStart
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
            if (currentState == DESTROYED) {
                //这里就是为什么通过observer()注册的Observer,
                //不需要像observeForever()注册的Observer需要手动解绑的原因。
                //因为这里会判断当前的状态是否处于DESTROYED,
                //如果当前Observer是在Activity下注册的,你可以理解成,
                //判断当前状态是否是Activity onDestroy() 的时候
                //如果是则手动removeObserver,这样就不需要我们手动解除监听啦
                //哪有什么岁月静好,只是有人替我们负重前行而已~
                //这里只是Observer自己替我们处理了解绑的脏活~

                removeObserver(mObserver);
                return;
            }
            Lifecycle.State prevState = null;

            //这里可以看到,如果prevState != currentState
            //就会执行activeStateChanged(shouldBeActive)
            //还记得这个方法吗?这个就是我让你们前面在observeForever()中记住的
            //忘记的朋友可以往回看下~
            //这里如果shouldBeActive()返回true,也就是当前处于活跃状态时。
            //现在矛头都指向了activeStateChanged(),那么让我们看下这里干了啥吧~
            
            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);
        }
    }

解析:根据在code中的解析,现在矛头全部指向activeStateChanged(),聪明的你也许猜到了,这个方法是不是藏着 为什么observe()是注册带生命周期的观察者,而observeForever()是注册非生命周期感知的观察者 的问题答案呢?让我们走向activeStateChanged()方法中一探究竟~

/**
 * 这是我截取LiveData.java中的部分代码
 */

private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        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;
            changeActiveCounter(mActive ? 1 : -1);
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

解析:这个方法是ObserverWrapper中的,如果传入的参数newActive为true,那么会走到dispatchingValue(this), “尿”到了,我全'尿'到了~,这个activeStateChanged()方法就是这个问题的答案,这也能解释为什么通过observeForever()注册的Observer是不带生命周期感知的(例:如果注册在Activity中,可以在onCreate,onStart,onResume,onPause,onStop,onDestory中收到值的变化,而使用observer()注册的Observer只能在onCreate,onStart,onResume中接收到值的变化),顺带提一点,在最终事件分发的 considerNotify() 中还有这么一个判断

/**
 * 这是我截取LiveData.java中的部分代码
 */

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.
        
        //官方注释意思:检查最新状态b4调度。也许它改变了状态,但我们还没有得到事件。
        //我们仍然首先检查observer.active以保持它作为事件的入口。所以即使
        //观察者移动到活动状态,如果我们没有收到该事件,
        //我们最好不要通知以获得更可预测的通知顺序。
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }


        //------------------与本次分析无关code------------------
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

解析:为什么会说到这个方法呢?因为我们还需要看下AlwaysActiveObserver

/**
 * 这是我截取LiveData.java中与 observeForever()方法 相关的的部分代码
 */

private class AlwaysActiveObserver extends ObserverWrapper {

        AlwaysActiveObserver(Observer<? super T> observer) {
            super(observer);
        }
        
        //嘿嘿,这里我返回的也是true,所以根本不可能走到那个判断中
        //所以我是一个无视生命周期的观察者~
        //只要注册我了,随时随地都可以收到onChange()回调
        //除了宿主GG或解绑我的时候,我收不到之外~
        @Override
        boolean shouldBeActive() {
            return true;
        }
    }

总结:至此你应该对我有所了解了,相信你了解我的原理后,对你以后的开发会有帮助的,就这样,完结撒❀~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐小歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值