LiveData使用、LiveData源码分析

简介

LiveData是可观察的数据持有者类。与常规的可观察对象不同,LiveData具有生命周期感知功能,这意味着它尊重其他应用程序组件(例如活动,片段或服务)的生命周期。这种意识确保LiveData仅更新处于活动生命周期状态的应用程序组件观察者。

LiveData的优点

1、确保用户界面与数据状态匹配
LiveData遵循观察者模式。Lifecycle对象生命周期状态更改时,LiveData会通知对象。这样不用单独处理数据比ui早的问题。
2、没有内存泄漏
观察者绑定到 Lifecycle对象,并在其相关的生命周期被破坏时自行清理。
3、活动停止不会导致崩溃
如果观察者的生命周期处于非活动状态(例如Activity处于非活动状态),则观察者不会收到任何LiveData事件。
4、不再需要人工生命周期处理
UI组件仅观察相关数据,而不会停止或继续观察。LiveData自动管理所有这些,因为它在观察的同时知道相关生命周期状态的变化。
5、始终最新的数据
如果生命周期变为非活动状态,则在再次处于活动状态时它将接收最新数据。例如,在后台的Activity返回到前台后会立即接收最新数据。
6、正确的配置更改
如果由于配置更改(例如设备旋转)而重新创建Activity或Fragment,则该Activity或者Fragment将立即接收最新的可用数据。
7、共享资源
LiveData 使用单例模式扩展对象以包装系统服务,以便可以在您的应用程序中共享它们。该LiveData对象一次连接到系统服务,然后任何需要资源的观察者都可以监视该LiveData 对象。

LiveData的使用

1、创建LiveData对象

public class NameViewModel {

// Create a LiveData with a String
private MutableLiveData<String> currentName;

    public MutableLiveData<String> getCurrentName() {
        if (currentName == null) {
            currentName = new MutableLiveData<String>();
        }
        return currentName;
    }
}

2、观察LivewData对象

public class NameActivity extends AppCompatActivity {

    private NameViewModel model;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
		......
        model = new NameViewModel();

        // Create the observer which updates the UI.
        final Observer<String> nameObserver = new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String newName) {
                // Update the UI, in this case, a TextView.
                nameTextView.setText(newName);
            } 
        }; 

        //观察LiveData,并以LifecycleOwner和观察者的身份传入此活动。
        model.getCurrentName().observe(this,nameObserver); 
    } 
}

Observer在收到LiveData状态变更回调onChanged()方法。有些时候可能项目中并没有实现Lifecycle并且着急使用LiveData,可以使用observeForever()方法,但是在Activity或者Fragment销毁时记得removeObserver。
3、更新LiveData数据

button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        String anotherName = "John Doe";
        model.getCurrentName().setValue(anotherName);
    }
});

如果主线程调用setValue(),子线程调用postValue()

LiveData可以扩展封装耗时任务等

一般我们在项目中会使用RxJava等请求耗时任务,会在Activity.onCreate中启动任务,onDestroy销毁任务,同时还得处理回调。这些扩展LiveData就可以做到!!

	public class GetNameLiveData extends LiveData<String> {
        private NetworkRequestManager manager;
		// listener用于监听网络数据,监听到后setValue通知所有观察者
        private NetworkDataCallBack listener = new NetworkDataCallBack() {
            @Override
            public void onNameUpload(String name) {
            	if (isMainThread) {
                	setValue(name);
                } else {
                	postValue(name);
                }
            }
        };

        public GetNameLiveData() {
            manager = new NetworkRequestManager();
        }
		// onActive会在有Observe添加的时候调用
        @Override
        protected void onActive() {
        	// 这里请求网络,获取name,注意这个回调是主线程回调
        	new Thread(new Runnable() {
            	@Override
            	public void run() {
               	 	manager.requestName(listener);
            	}
        	}).start();
        }
		// onInactive会在没有任何Observe的时候调用
        @Override
        protected void onInactive() {
        	// 这里取消网络请求
            manager.cacelRequest();
        }
		private boolean isMainThread() {
        	return Looper.myLooper() == Looper.getMainLooper();
    	}
    }
	// 定义网络请求的接口回调
    private interface NetworkDataCallBack {
        void onNameUpload(String name);
    }

这样处理就不用切换线程、不用分发数据,不用随着Activity生命周期启动和取消任务。

LiveData获取数据后做链式转换传输

需求场景:例如,从网络获取到商品信息是一个json的String,既有android数据库监听存储这个json,又有UI获取到数据做展示。你可以通过此方法转换。

		MutableLiveData<String> liveData = new MutableLiveData<>();
        liveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                // 存储到数据库
            }
        });

        LiveData<ProductInfo> productInfoLiveData = Transformations.map(liveData, new Function<String, ProductInfo>() {
            @Override
            public ProductInfo apply(String json) {
                return new ProductInfo(json);
            }
        });
		// 这么做就不用每个地方处理ProductInfo转换了
        productInfoLiveData.observe(this, new Observer<ProductInfo>() {
            @Override
            public void onChanged(ProductInfo productInfo) {
                // UI 展示
            }
        });

维护可变的LiveData对象

需求:例如,你需要通过一个name参数获取一个LiveData对象,然后添加Observe监听这个LiveData对象。
一般做法:

	class MyViewModel {
        private final HashMap<String, LiveData<String>> mLiveDataMap;

        public MyViewModel(HashMap<String, LiveData<String>> liveDataMap) {
            mLiveDataMap = liveDataMap;
        }

        public LiveData<String> getNameMapLiveData(String name) {
            return mLiveDataMap.get(name);
        }
    }

分析下这个做法的弊端:
很明显,因为getNameMapLiveData获取到的是不同的LiveData对象,所以监听这个LiveData的Observer对象,需要每次getNameMapLiveData获取到新的LiveData对象后再做一次addObserve()操作,同时还需要解除之前观察的LiveData对象。

谷歌提供的神奇的办法:

	class MyViewModel {
        private final HashMap<String, LiveData<String>> mLiveDataMap;

        private final MutableLiveData<String> nameLiveData = new MutableLiveData();

        public final LiveData<String> mNameMapLiveData;

        public MyViewModel(HashMap<String, LiveData<String>> liveDataMap) {
            mLiveDataMap = liveDataMap;
            mNameMapLiveData = Transformations.switchMap(nameLiveData, new Function<String, LiveData<String>>() {
                @Override
                public LiveData<String> apply(String name) {
                    return mLiveDataMap.get(name);
                }
            });
        }

        private void setName(String address) {
            nameLiveData.setValue(address);
        }
    }

Transformations.switchMap自动帮你把Observe做了转换,你不再需要自己处理LiveData对象替换导致的观察者变动。

合并多个LiveData

MediatorLiveData允许您合并多个LiveData。只要MediatorLiveData对象发生更改,就会触发它的LiveData集合。

例如,如果LiveData在UI中有一个可以从本地数据库或网络更新的对象,则可以将以下源添加到该 MediatorLiveData对象:

LiveData与存储在数据库中的数据关联的对象。
LiveData与从网络访问的数据关联的对象

LiveData源码分析

一、LiveData如何分发Observe的
1、先看下LiveData的observe()方法

	private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
            new SafeIterableMap<>();
            
	public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        ......
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        ......
    }

很明显新增的观察者放到了mObservers集合
2、setValue是如何分发的

	protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
    	......
        for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
            considerNotify(iterator.next().getValue());
			if (mDispatchInvalidated) {
				break;
            }
        }
        ......
    }

这里看到对mObservers集合做了遍历,最终到了considerNotify()

private void considerNotify(ObserverWrapper observer) {
		......
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);
    }

很简单就是一个集合的遍历,啥也没有。回调observer.onChanged方法。
3、看下子线程的postValue()

	protected void postValue(T value) {
        ......
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
    private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            setValue((T) newValue);
        }
    };

也很简单,利用ArchTaskExecutor回调到了主线程,主线程setValue()分发。

二、LiveData关联Lifecycle,避免内存泄露
对Lifecycle使用不理解的,可以先看下这篇文章lifecycle原理分析
1、还是先看下Observe()方法

    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        ......
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        ......
        owner.getLifecycle().addObserver(wrapper);
    }

owner.getLifecycle().addObserver()很明显给包装的LifecycleBoundObserver添加了生命周期关联
2、看一下LifecycleBoundObserver

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

Lifecycle在状态为DESTROYED时把Observer全部移除了,所以关联了lifecycle的LiveData不会发生内存泄露问题。
三、Transformations.map原理
1、看下MediatorLiveData包装类

public class MediatorLiveData<T> extends MutableLiveData<T> {
    private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();
    
    public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
        Source<S> e = new Source<>(source, onChanged);
        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()) {
            e.plug();
        }
    }
    
    private static class Source<V> implements Observer<V> {
        final LiveData<V> mLiveData;
        final Observer<? super V> mObserver;
        int mVersion = START_VERSION;

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

        void plug() {
            mLiveData.observeForever(this);
        }

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

        @Override
        public void onChanged(@Nullable V v) {
            if (mVersion != mLiveData.getVersion()) {
                mVersion = mLiveData.getVersion();
                mObserver.onChanged(v);
            }
        }
    }
}

MediatorLiveData很明显做了一个LiveData的包装集合。addSource()对传入的LiveData对象增加了一个新的Observe观察者,这个新增的观察者又桥接到了addSource()传入的Observer。
2、看下Transformations.map()方法

    public static <X, Y> LiveData<Y> map(
            @NonNull LiveData<X> source,
            @NonNull final Function<X, Y> mapFunction) {
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(source, new Observer<X>() {
            @Override
            public void onChanged(@Nullable X x) {
                result.setValue(mapFunction.apply(x));
            }
        });
        return result;
    }

这里会有点绕。map()方法最终的结果就是当source这个LiveData对象发生变更时,会分发到addSource()的第二个参数的onChanged()方法。因为result本身就是一个LiveData,所以调用result.setValue()就成功的链式分发到了map返回的LiveData对象。而mapFunction.apply(x)就是做了下数据处理。
四、Transformations.switchMap原理
搞懂了Map方法,switchMap就好理解一些了。
直接看switchMap代码:

    public static <X, Y> LiveData<Y> switchMap(
            @NonNull LiveData<X> source,
            @NonNull final Function<X, LiveData<Y>> switchMapFunction) {
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(source, new Observer<X>() {
            LiveData<Y> mSource;

            @Override
            public void onChanged(@Nullable X x) {
                LiveData<Y> newLiveData = switchMapFunction.apply(x);
                if (mSource == newLiveData) {
                    return;
                }
                if (mSource != null) {
                    result.removeSource(mSource);
                }
                mSource = newLiveData;
                if (mSource != null) {
                    result.addSource(mSource, new Observer<Y>() {
                        @Override
                        public void onChanged(@Nullable Y y) {
                            result.setValue(y);
                        }
                    });
                }
            }
        });
        return result;
    }

这里的代码看着也会有点绕。跟map方法的不同是这里的onChange做了两次Observe观察者传递,当switchMapFunction.apply(x)返回新的LiveData对象后,会重新为这个对象添加一个Obsever,然后当新的LiveData对象状态变更时会通过这个Observe通知result。

这里根据代码解析switchMap的优点
(1)上边讲了switchMap会动态的变更LiveData对象,那么如何保证变更LiveData对象后,Observe集合没有变动呢?
final MediatorLiveData result = new MediatorLiveData<>();很明显,switchMap返回的result是一个new LiveData,并不是LiveData newLiveData = switchMapFunction.apply(x)返回的LiveData,所以虽然我们在apply变动了LiveData,但是switchMap返回的LiveData对象从来没有变过。
(2)switchMap会变更LiveData,如何保证已经废弃的LiveData不会再触发Observe观察者?

if (mSource != null) {
	result.removeSource(mSource);
}

因为MediatorLiveData对象内部有一个LiveData集合,所以remove掉后,集合遍历就找不到这个失效的LiveData对象了,也就不会触发Observe。

猜你喜欢

转载自blog.csdn.net/archie_7/article/details/105687751