Android架构组件系列-LiveData源码分析


上篇文章介绍了 Lifecycle组件,Lifecycle主要用于解决生命周期相关的问题,LiveData是以Lifecycle为基础的拓展,解决了跟数据相关的一些问题,本文呢就来介绍下LiveData的牛逼之处吧。

有生命的LiveData

其实,LiveData从它的英文上看就能有所感触,活着的数据,嗯,我觉得很形象。我们在开发过程中,组件所持有的数据确实一直都是死气沉沉的,数据完全要由我们通过代码去生成,去改变,去传递,数据似乎只有存储信息的作用。但是LiveData的出现,就给好像给数据赋予了生命一样,你会发现,数据能自己做一些事情了!!!

LiveData特征

我们先来了解下LiveData的特征:

  1. LiveData可以持有数据,它可以被观察,被订阅。当其持有的数据发生变化时,LiveData会“考虑”给它的观察者或者说订阅者们发送通知。
  2. LiveData可以感知订阅它的组件生命周期。只有组件处于激活状态时,LiveData才会把数据更新通知发送给组件。

注意:上述和下文中将会提到的“组件”,是指实现了LifecycleOwner接口的组件,即使用了Lifecycle组件,一般是指Activity或者Fragment。

LiveData优点

  • 促使数据变化和UI界面高度同步:当LiveData的数据发生变化时,它会通知处于激活状态的观察者(组件),观察者们就能及时的相应执行更新UI的处理;
  • 强大的数据变化通知机制:由于LiveData能感知组件的生命周期,所以,当组件处于非激活状态时,该组件不会收到LiveData的数据变化通知,这样就能避免一些比较难解决的崩溃问题(比如当我们执行网络请求时,数据还没回调,组件就被销毁了,当数据回调回来时执行更新UI操作就会崩溃)。一旦组件恢复激活状态,LiveData就会把最新的数据变化通知发送给该组件。这样的通知机制真的很合理,很AI~
  • 避免内存泄漏:在LiveData“考虑”给其观察者发送通知时,会检查观察的生命周期,当观察者处于DESTORYED状态时,LiveData会主动的清除该观察者,可以很好的避免内存泄漏。
  • 能够保护用户数据:这里需要配合另外一个组件ViewModel来实现,此时,我们不会讲用户数据直接存放在组件中,而是放在LiveData中,由ViewModel持有LiveData,ViewModel负责向组件提供LiveData的访问接口,这样就完成了数据和组件的分离,当组件遇到如屏幕方向改变等变化时,就可以直接从ViewModel中重新获取数据并恢复UI,而不需要我们再像以前一样做复杂的数据保护措施(利用onSaveInstanceState方法);

用一用LiveData

上面说了一堆偏概念的东西,脑子发胀,还是用程序猿的语言交流一下吧。

准备工作:添加依赖

dependencies {
	def lifecycle_version = "2.0.0"
    // ViewModel and LiveData
    compile "android.arch.lifecycle:extensions:$lifecycle_version"
}

LiveData的使用方式:

1. 直接使用一些Google定义好的LiveData;
2. 继承LiveData,自己搞一个实现类来用;

直接使用LiveData对象

  • 创建LiveData对象实例:(配合ViewModel使用效果更佳)
public class NameViewModel extends ViewModel {
    // 创建一个持有String类型数据的LiveData
    private MutableLiveData<String> mCurrentName;
    // 创建一个持有String类型列表数据的LiveData
    private MutableLiveData<List<String>> mNameListData;

	// 对外提供访问接口
    public MutableLiveData<String> getCurrentName() {
        if (mCurrentName == null) {
            mCurrentName = new MutableLiveData<>();
        }
        return mCurrentName;
    }

	// 对外提供访问接口
    public MutableLiveData<List<String>> getNameList(){
        if (mNameListData == null) {
            mNameListData = new MutableLiveData<>();
        }
        return mNameListData;
    }
}

MutableLiveData是LiveData的子类,是组件中已经定义好的LiveData实现类之一,源码分析时,我们会介绍到,莫急~

  • 创建Observer对象,添加观察者
public class LiveDataFragment extends Fragment {
    private static final String TAG = "LiveDataFragment";
    
    private NameViewModel mNameViewModel;
    
    @BindView(R.id.tv_name)
    TextView mTvName;

    public static LiveDataFragment getInstance(){
        return new LiveDataFragment();
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 获取ViewModel
        mNameViewModel = ViewModelProviders.of(this).get(NameViewModel.class);
        
        // 订阅LiveData中当前Name数据变化,以lambda形式定义Observer
        mNameViewModel.getCurrentName().observe(this,(String name) -> {
            mTvName.setText(name);
            Log.d(TAG, "currentName: " + name);
        }); 
        // 订阅LiveData中Name列表数据变化,以lambda形式定义Observer
        mNameViewModel.getNameList().observe(this, (List<String> nameList) -> {
            for (String item : nameList) {
                Log.d(TAG, "name: " + item);
            }
        }); 
    }

    @Nullable
    @Override
	public View onCreateView(LayoutInflater inflater, 
	@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.layout_livedata, container, false);
        ButterKnife.bind(this, view);
        return view;
    }
}

代码中,我们在onCreate()方法中通过LiveData.observe()方法添加观察者,当数据变化时会通过回调方法通知观察者,在lambda表达式中更新当前姓名和打印姓名列表。看上去和Lifecycle用法很相似啊。

  • 更新LiveData中的数据
@OnClick({R.id.btn_change_name, R.id.btn_update_list})
void onClicked(View view){
    switch (view.getId()){
        case R.id.btn_change_name:
            mNameViewModel.getCurrentName().setValue("Jane");
            break;
        case R.id.btn_update_list:
            List<String> nameList = new ArrayList<>();
            for (int i = 0; i < 10; i++){
                nameList.add("Jane<" + i + ">");
            }
            mNameViewModel.getNameList().setValue(nameList);
            break;
    }
}

代码很简单,在两个按钮的点击事件中通过LiveData.setValue()方法来改变LiveData中保存的数据。当点击这两个按钮的时候,我们会发现在onCreate()方法中会收相应到数据改变的回调。一般我们会通过ViewModel来改变数据,这里就偷懒了。

继承LiveData类

public class MyLiveData extends LiveData<Integer> {
    private static final String TAG = "MyLiveData";
    private static MyLiveData sData;
    private WeakReference<Context> mContextWeakReference;

    public static MyLiveData getInstance(Context context){
        if (sData == null){
            sData = new MyLiveData(context);
        }
        return sData;
    }

    private MyLiveData(Context context){
        mContextWeakReference = new WeakReference<>(context);
    }

    @Override
    protected void onActive() {
        super.onActive();
        registerReceiver();
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        unregisterReceiver();
    }

    private void registerReceiver() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
        mContextWeakReference.get().registerReceiver(mReceiver, intentFilter);
    }

    private void unregisterReceiver() {
        mContextWeakReference.get().unregisterReceiver(mReceiver);
    }


    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d(TAG, "action = " + action);
            if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
                int wifiRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
                int wifiLevel = WifiManager.calculateSignalLevel(wifiRssi, 4);
                sData.setValue(wifiLevel);
            }
        }
    };
}

这个例子中,使用了单例模式,加上LiveData,强强联手,实现了一个资源共享的作用。
我们在onActive()和onInactive()方法中分别注册监听和反注册监听WIFI信号强度广播。然后在广播接收者中更新MyLiveData对象中的数据。需要监听这个广播的地方就不用注册监听这个广播了(组件销毁的时候你还要反注册,很烦),直接通过MyLiveData.getInstance()方法获取LiveData,然后调用observe()方法,通过观察这个LiveData来获取WIFI强度变化信息。代码嘛,我偷懒咯。
onActive(),当处于激活状态的observer个数从0到1时,该方法会被调用。
onInactive() ,当处于激活状态的observer个数从1变为0时,该方法会被调用。

嗯,一顿代码下来,我们发现,正常的流程中,我们要在组件中做数据处理,当组件或者其他某个地方获取到数据或者改变了数据时,我们要通过各种手段通知到组件(回调接口啦,EventBus啦),其实LiveData是帮我们省略了数据变更通知这个环节,让我们将关注点集中在数据处理上,再也不用一层一层的写回调(又名:回调地狱)啦,再也不用写onEvent了。

深入分析

到这里,我们已经对LiveData有了大致了解了,嗯,我们已经了解了它的外表,那么它的内涵呢?

类关系图

在这里插入图片描述

这是LiveData的整体类关系图,还是比较简单的。我们来一个个分析下:

  • LiveData
    我们先大致了解下LiveData里面有什么,我们后面会详细介绍其细节。
// LiveData是一个抽象类,但是没有抽象方法
public abstract class LiveData<T> {
    ......
    // 它维护了一个Map集合,用于存储观察者;
    // 这一手和Lifecycle好像啊。。。
    private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers =
            new SafeIterableMap<>();

	......
	
	// 考虑是否派发数据变化通知
	private void considerNotify(ObserverWrapper observer) {
		......
	}

	// 最终派发数据变化通知方法
	private void dispatchingValue(@Nullable ObserverWrapper initiator) {
		......
	}
	
	// 添加观察者方法
	public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
		......
	}

	// 添加永久激活状态观察者
	public void observeForever(@NonNull Observer<T> observer) {
		......
	}
	
	// 移除观察者
	public void removeObserver(@NonNull final Observer<T> observer) {
		......
	}

	protected void postValue(T value) {
        ......
    }

    // 设置数据
    @MainThread
    protected void setValue(T value) {
        ......
    }

   	 // 获取数据
    @Nullable
    public T getValue() {
		......
    }
	
	......
	// onInactive()和 onActive()方法一般是在继承LiveData类时被实现的方法
	// 能帮助LiveData在没有任何观察者的情况下释放任何繁重的资源。
    protected void onActive() {
    }
    
    protected void onInactive() {
    }
    
	......
	
	// LifecycleBoundObserver是它的内部类,这个类实现了GenericLifecycleObserver接口(重点哟);
    class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
         ......
    }

    // 私有的抽象类ObserverWrapper,用于包装观察者;
    private abstract class ObserverWrapper {
         ......
    }

	// 配合observeForever()方法使用,此时,默认观察者永久的处于激活状态,需要手动调用removeObserver()移除该观察者
    private class AlwaysActiveObserver extends ObserverWrapper {
		 ......
    }
}
  • LifecycleBoundObserver
    LifecycleBoundObserver,它实现了GenericLifecycleObserver,而GenericLifecycleObserver继承了LifecycleObserver接口。在这里可以回顾下Lifecycle组件相关的内容。当组件(Fragment、Activity)生命周期变化时会通过onStateChanged()方法回调过来。
    class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @NonNull final LifecycleOwner mOwner;

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

        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }

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

        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }
  • Observer
    Observer接口就是观察者,其中定义了LiveData数据变化的回调方法onChanged()。
/**
* A simple callback that can receive from {@link LiveData}.
*
* @param <T> The type of the parameter
*
* @see LiveData LiveData - for a usage description.
*/
public interface Observer<T> {
   /**
    * Called when the data is changed.
    * @param t  The new data
    */
   void onChanged(@Nullable T t);
}
  • MutableLiveData
    LiveData的常用子类,它公开了LiveData的setValve和postValue方法。
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);
    }
}
  • MediatorLiveData
    继承了MutableLiveData,它可以添加并观察其他LiveData,就是说,MediatorLiveData的观察者,可以收到被MediatorLiveData添加进来的LiveData的数据变化通知,吊炸天,一次性完成了对多个数据的变化监听。
/**
 * {@link LiveData} subclass which may observer other {@code LiveData} objects and react on
 * {@code OnChanged} events from them.
 * <p>
 * This class correctly propagates its active/inactive states down to source {@code LiveData}
 * objects.
 * 这个类可以正确的把他的active/inactive状态传递给他的数据源
 * @param <T> The type of data hold by this instance
 */
@SuppressWarnings("WeakerAccess")
public class MediatorLiveData<T> extends MutableLiveData<T> {
    // 维护了一个Map集合,用于存储其他数据源(LiveData)
    private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();

    /**
     * Starts to listen the given {@code source} LiveData, {@code onChanged} observer will be called
     * when {@code source} value was changed.
     * <p>
     * {@code onChanged} callback will be called only when this {@code MediatorLiveData} is active.
     * <p> If the given LiveData is already added as a source but with a different Observer,
     * {@link IllegalArgumentException} will be thrown.
     */
    @MainThread
    public <S> void addSource(LiveData<S> source, Observer<S> onChanged) {
        // Source实现了Observer接口,所以可以说是一个观察者
        Source<S> e = new Source<>(source, onChanged);
        // 存储逻辑和LiveData一样
        Source<?> existing = mSources.putIfAbsent(source, e);
        if (existing != null && existing.mObserver != onChanged) {
            throw new IllegalArgumentException(
                    "This source was already added with the different observer");
        }
        if (existing != null) {
            return;
        }
        if (hasActiveObservers()) {
            // 如果MediatorLiveData存在激活的观察者,就让LiveData添加观察者Source
            e.plug();
        }
    }

    /**
     * Stops to listen the given {@code LiveData}.
     *
     * @param toRemote {@code LiveData} to stop to listen
     * @param <S>      the type of data hold by {@code source} LiveData
     */
    @MainThread
    public <S> void removeSource(LiveData<S> toRemote) {
        Source<?> source = mSources.remove(toRemote);
        if (source != null) {
            source.unplug();
        }
    }

    @CallSuper
    @Override
    protected void onActive() {
        // 当MediatorLiveData的观察者数目从0变成1时,就遍历其持有的所有LiveData,让LiveData添加观察者Source
        for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
            source.getValue().plug();
        }
    }

    @CallSuper
    @Override
    protected void onInactive() {
        // 当MediatorLiveData的观察者数目从1变成0时,就遍历其持有的所有LiveData,让LiveData移除观察者Source
        for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
            source.getValue().unplug();
        }
    }

    private static class Source<V> implements Observer<V> {
        final LiveData<V> mLiveData;
        final Observer<V> mObserver;
        int mVersion = START_VERSION;

        Source(LiveData<V> liveData, final Observer<V> observer) {
            mLiveData = liveData;
            mObserver = observer;
        }

        void plug() {
            // 添加观察者Source,Source实现了Observer接口,所以可以被LiveData添加为观察者
            // 由于Source不存在生命周期,所以调LiveData.observeForever()方法
            mLiveData.observeForever(this);
        }

        void unplug() {
            mLiveData.removeObserver(this);
        }

        @Override
        public void onChanged(@Nullable V v) {
            // 当LiveData数据发生变化时,会回调到这里
            if (mVersion != mLiveData.getVersion()) {
                mVersion = mLiveData.getVersion();
                // 此时会直接通知mObserver数据变化了,这个mObserver是通过addSource方法添加进来的观察者
                mObserver.onChanged(v);
            }
        }
    }
}

注意:通过代码我们发现,MediatorLiveData里面添加的LiveData,只有在MediatorLiveData的处于active状态时(就是MediatorLiveData存在激活的观察者),LiveData的数据变化才会通知到他们的观察者。

LiveData使用时序图

在这里插入图片描述
使用LiveData的过程中主要涉及到的重点有三个:

  • 在Fragment/Activity中通过LiveData.observer()添加观察者。
  • 根据Fragment/Activity生命周期发生变化,移除观察者或者考虑通知观察者更新数据。
  • 调用LiveData的setValue()或postValue()方法后,考虑通知观察者更新数据。

我们来通过源码分析这三个重点。

Point.1 添加观察者

LiveData提供了两种添加观察者的方法:observeForever()、observe()。

   @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        // 将LifecycleOwner对象和Observer对象封装成LifecycleBoundObserver对象
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        
        // putIfAbsent()方法是判断容器中的observer(key)是否有已经和wrapper(value)关联
        // 如果已经关联则返回关联值,否则关联并返回wrapper
        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;
        }
       	// 最后,添加LifecycleOwner的生命周期观察者
        owner.getLifecycle().addObserver(wrapper);
    }

    @MainThread
    public void observeForever(@NonNull Observer<T> observer) {
    	// 该观察者一直处于激活状态
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        wrapper.activeStateChanged(true);
    }

结合上文中的LifecycleBoundObserver源码,LifecycleBoundObserver实现了GenericLifecycleObserver接口,成为生命周期观察者,在observe方法的最后一步,给LifecycleOwner对象添加了观察者,这样我们就实现了LiveData的重要特征:与组件生命周期想关联,LiveData能感知组件生命周期变化。

Point.2 组件生命周期变化引起LiveData启动数据更新流程

LifecycleBoundObserver源码中,当组件(Fragment/Activity)生命周期发生变化时,onStateChanged()方法会被调用。此时,我们会判断组件的生命周期,如果是DESTORYED,就移除观察者。如果不是,我们就调用ObserverWrapper中的activeStateChanged方法,考虑向组件发送数据更新通知。

private abstract class ObserverWrapper {
        final Observer<T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;

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

        abstract boolean shouldBeActive();

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

        void activeStateChanged(boolean newActive) {
        	// 组件生命周期变化,不一定激活状态发生变化,
        	// 如从start -> resume,组件只是状态从STARTED变为RESUMED,但是一直都是激活的,
        	// 在LifecycleBoundObserver的shouldBeActive()方法中我们看到,
        	// 只要至少是STARTED状态,都会返回true,也就是激活状态
            if (newActive == mActive) {
            	// 组件激活状态未发生变化,则不派发数据更新
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            // 下面2个if语句,验证了上面我们说的调用onActive()和onInactive()的时机
            if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
            	// 组件处于激活状态,就考虑派发数据更新。
                dispatchingValue(this);
            }
        }
    }

这里,我们又看到了LiveData的重要特征:组件生命周期变化时,LiveData会根据组件的状态做出不同的处理,实现了组件销毁时就移除该观察者,组件处于非激活时,不发送通知,组件变为激活态时,再发送通知。
上文中,我们提到,LiveData发送通知时,是考虑,而不是直接发通知,为什么要用考虑呢,我们看下dispatchingValue()方法的具体实现。

    private void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            // initiator 不为空是组件生命周期变化引起的LiveData启动数据变化通知流程
            // 所以LiveData只会考虑给指定的观察者发送通知
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
            	// 此处是,当调用LiveData的setValue或postValue方法时触发的流程
            	// 此时,LiveData会考虑向其所有的观察者发送通知
                for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

我们来看下很重要的considerNotify()方法,看看LiveData是如何“考虑”的:

	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;
        }
        // 这里的version是指LiveData所持有的数据的版本号,
        // 也就是说LiveData持有的数据发生一次变化,version就会自增,
        // 如果观察中数据的版本比此次通知中的数据版本新的话,就不会执行通知
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        // 最终调用观察者接口方法onChanged()方法回调最新的数据给观察者
        observer.mObserver.onChanged((T) mData);
    }

从源码中我们看到,其实LiveData的“考虑”,其实就是在不断的检查观察者的状态。

Point.3 数据变化引起LiveData启动数据更新流程

LiveData提供了两种改变数据的方法:setValue()和postValue()。区别是setValue()要在主线程中调用,而postValue()既可在主线程也可在子线程中调用。

注意,此时,这两个方法的访问权限都是protected,我们需要通过MutableLiveData来调用。

我们先看setValue()方法的具体实现:

    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        // 增加数据的版本号
        mVersion++;
        mData = value;
        // 直接调用数据分发方法
        dispatchingValue(null);
    }

assertMainThread()方法用于判断当前线程是否是主线程,不是就抛出异常。

我们再看下postValue()方法的具体实现:

    /**
     * Posts a task to a main thread to set the given value. So if you have a following code
     * executed in the main thread:
     * <pre class="prettyprint">
     * liveData.postValue("a");
     * liveData.setValue("b");
     * </pre>
     * The value "b" would be set at first and later the main thread would override it with
     * the value "a".
     * <p>
     * If you called this method multiple times before a main thread executed a posted task, only
     * the last value would be dispatched.
     *
     * @param value The new value
     */
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

	// postValue中发送的Runnable对象
	private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            // 最终还是通过setValue方法来实现数据修改和通知
            setValue((T) newValue);
        }
    };

从官方的注释上我们得知,setValue会立刻执行,postValue方法是向主线程发送了一个设置数据的任务,会被加入到主线程的消息队列中,顺序执行。

转化LiveData

在日常开发中,我们肯定会遇到,我们拿到的数据并不是我们最终想要的,我们需要对这个数据进行加工或者转换。用过RxJava的同学表示这都不是事儿~
所以,Google也提供了一个类来协助我们完成这块工作,那就是Transformations类,在Lifecycle的包下。Transformations中只有两个方法:map() 和 switchMap()。

map()

map方法很好理解,就是将一个LiveData中的值,经过处理后,传递给另外一个LiveData,实现了数据转换。

    @MainThread
    public static <X, Y> LiveData<Y> map(LiveData<X> source, final Function<X, Y> func) {
    	// 转换后的LiveData是一个MediatorLiveData
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(source, new Observer<X>() {
            @Override
            public void onChanged(@Nullable X x) {
            	// func.apply(x)是需要我们自己实现的转换逻辑
                result.setValue(func.apply(x));
            }
        });
        return result;
    }

switchMap()

从源码上看,switchMap是将对某个LiveData的监听转换成对新的LiveData的监听。和map()还是有很大区别的。

@MainThread
    public static <X, Y> LiveData<Y> switchMap(LiveData<X> trigger,
            final Function<X, LiveData<Y>> func) {
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        // 这里看上去是对trigger的监听,但是trigger的变化不会反馈给观察者
        result.addSource(trigger, new Observer<X>() {
            LiveData<Y> mSource;

            @Override
            public void onChanged(@Nullable X x) {
            	// 要求转换方法返回一个LiveData
                LiveData<Y> newLiveData = func.apply(x);
                if (mSource == newLiveData) {
                    return;
                }
                if (mSource != null) {
                    result.removeSource(mSource);
                }
                mSource = newLiveData;
                if (mSource != null) {
                	// trigger发生变化后,最终会导致result添加newLiveData监听
                	// newLiveData数据变化了,才会引发result回调数据给观察者
                    result.addSource(mSource, new Observer<Y>() {
                        @Override
                        public void onChanged(@Nullable Y y) {
                            result.setValue(y);
                        }
                    });
                }
            }
        });
        return result;
    }

以上就是对LiveData的整体分析啦,有什么不对的地方,欢迎小伙伴们指正,轻喷~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值