kotlin相关专题

LiveData使用与解析

2019-04-01  本文已影响0人  炸山哥

上一篇文章ViewModel简单使用与解析我们说了ViewModel相关的知识,接下来我们要说的是ViewModel的终极搭档LiveData。
先来说一下LiveData的优点:

1.创建LiveData对象

public class MViewModel extends ViewModel {

    MutableLiveData<String> mString;

    public MutableLiveData<String> getString(){
        if(mString==null){
            mString=new MutableLiveData<>();
        }
        return mString;
    }

    public MutableLiveData<String> getMsgString(){
        if(msgString==null){
            msgString=new MutableLiveData<>();
        }
        return msgString;
    }
}

一般都是在ViewModel中声明和保存LiveData,这有利于:

2.订阅LiveData对象

官方推荐在应用程序组件的onCreate()方法开始观察LiveData对象,理由是:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView=findViewById(R.id.desc);
        mViewModel = ViewModelProviders.of(this).get(MViewModel.class);
        mViewModel.getString().observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                Log.e("MainActivity", "耗时任务结束返回数据");
                mTextView.setText(s);
            }
});

3.更新LiveData对象

一般在ViewModel中对数据进行处理,当我们拿到数据后将值赋值给LiveData

    public void startTask(){
        new Thread(){
            @Override
            public void run() {
                //请求网络数据、数据库、加载大图等。
                //如果在Activity转屏的时候取消这些任务,那恢复的时候就要重新加载,势必浪费资源
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //更新LiveData
                mString.postValue("我是来自3秒后的数据");
                super.run();
            }
        }.start();
    }

setValue()或者postValue()都可以用来更新LiveData的值,区别在于:
setValue要在主线程中使用,postValue在后台线程中使用。

4.LiveData Transformations

有时候我们想在ViewModel中对LiveData进行数据转换之后再输出给observer,比如我我拿到了用户ID,我们需要通过ID拿到用户信息再去更新UI,那我们就可以用Transformations来对一个LiveData对象进行转换,Transformations类目前只提供两个转换方法map()和switchMap():

 static <X, Y> LiveData<Y> map(LiveData<X> source,Function<X, Y> mapFunction) {}
 static <X, Y> LiveData<Y> switchMap(LiveData<X> source,Function<X, LiveData<Y>> switchMapFunction){}

简单对比一下你会发现这两个方法只是最后一个传入的参数不同而已,返回结果跟第一个参数是一样的,至于选择哪个方法,就完全是看你要传入的参数类型了

    LiveData<Long> userId...;
    LiveData<UserBean> userBean=Transformations.map(userId, new Function<Long, UserBean>() {
        @Override
        public UserBean apply(Long input) {
            //比如说你刚好有个方法是通过userId获取到userBean,并且是返回UserBean类型的就用map
            return new UserBean();
        }
    });
    LiveData<UserBean> userBean=Transformations.switchMap(userId, new Function<Long, LiveData<UserBean>>() {
        @Override
        public LiveData<UserBean> apply(Long input) {
            //比如说你刚好有个方法是通过userId获取到userBean,并且是返回LiveData<UserBean>类型的就用switchMap
            return new MutableLiveData<UserBean>(){};
        }
    });

再来看下该类完整的代码

public class Transformations {

    private Transformations() {
    }

    @MainThread
    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;
    }

    @MainThread
    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;
    }
}

你会发现其实就是通过类把LiveData<X>转换成了MediatorLiveData<Y>输出。

5. MediatorLiveData

我们前面有提到过,只有LifecycleOwner对象才能使用observer方法对LiveData进行监听,而Transformations的转换思路显然是通过对上一个LiveData进行了监听然后在其值发生变化的时候封装成MediatorLiveData对象输出。所以应该是用到了LiveData的observeForever方法。
我们先来看下它的addSource方法

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

传入的LiveData和Observer被用来构造Source对象,看下Source代码

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() {
            //此处完成了对传入的LiveData的订阅
            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);
            }
        }
    }

果然是用到了observeForever对传入的LiveData进行了监听,然后在onChanged方法将值继续传递下去。而MediatorLiveData可以多少调用addSource,其内部用了一个Map来存储构造生成的Source对象。
MediatorLiveData相当于一个自定义的LiveData,其内部定义了一个Map用于存储

private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();

所以MediatorLiveData除了用于上面Transformations的转换操作之外还可用来做合并订阅的操作。

 * LiveData<Integer> liveData1 = ...;
 * LiveData<Integer> liveData2 = ...;
 *
 * MediatorLiveData<Integer> liveDataMerger = new MediatorLiveData<>();
 * liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));
 * liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value));

这样只要是liveData1、liveData2其中一个数据的变化都会引发liveDataMerger去发出更新数据的通知。

上一篇下一篇

猜你喜欢

热点阅读