谷歌架构组件(三)LiveData的使用与分析

LiveData is an observable data holder class.从谷歌的解释中我们可以知道LiveData是一个可观察的数据持有类。和普通的observable不同的是,LiveData可以感知activity,fragment,service等组件的生命周期变化,从而确保数据的更新是在组件的active状态周期执行。

使用LiveData具有如下优势:

确保UI和数据状态保持一致

LiveData属于观察者模式。当生命周期变化或者数据更新时,LiveData通知Observer对象发生变化,由observer的onChange响应执行UI更新。

没有内存泄漏

Observers 是和LifeCycle对象绑定的,当LifeCycle对象被onDestroy()时,observers则被clean up。

在stop activities时不会奔溃

当Observers的生命周期处于inactive状态时,例如activity被按返回键时,Observers将不会响应来自LiveData的事件。

不需要更多的手动管理生命周期

LiveData 负责自动管理生命周期

保证数据是最新的

比如处于后台的activity重新回到前台时,它将自动获得最新的数据。

响应屏幕旋转等配置变化

当activity或者fragment因为屏幕旋转,或者语言等配置改变而重建时,它将接收最新的数据。

共享资源

你可以extend LiveData,利用单例模式封装一些系统服务,当LiveData对象和系统服务连接后,所有需要该系统服务提供资源的observer可改为直接观察这个LiveData.

如何使用LiveData

  1. 创建LiveData实例持有特定类型的数据,通常放在你的自定义ViewModel类中。
public class NameViewModel extends ViewModel {

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

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

// Rest of the ViewModel...
}

  1. 创建Observer对象实现onChanged()函数,当LiveData对象持有的数据发生更改后,或activity,fragment等生命周期变化时,比如从后台进入前台时,onChanged()会被触发调用。

  2. 将Observer对象使用observer()函数attach到LiveData对象。

public class NameActivity extends AppCompatActivity {

    private NameViewModel mModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Other code to setup the activity...

        // Get the ViewModel.
        mModel = ViewModelProviders.of(this).get(NameViewModel.class);

        // 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.
                mNameTextView.setText(newName);
            }
        };

        // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
        mModel.getCurrentName().observe(this, nameObserver);
    }
}
更新LiveData 对象

调用LiveData的setValue()后,会直接触发Observer对象的onChange()函数。 如果是在非UI线程,调用postValue()函数。

eg:

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

响应式编程

如果你希望支持RxJava,可添加支持

dependencies {
    // ReactiveStreams support for LiveData
    implementation "android.arch.lifecycle:reactivestreams:1.1.0"
}


关于LiveData的高级用法:扩展Extend,转化Transform,合并Merge,本文不多介绍,感兴趣的同学请参考谷歌官网链接

代码分析:
livedata.png

LiveData的整体类组织关系还是非常清晰的。

核心类 LiveData


public abstract class LiveData<T> {


    /**
    * 添加observe对象
    **/
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
       ......
    }
    
    /**
    * 更新持有数据,触发onserve对象onChange()执行
    **/
    @MainThread
    protected void setValue(T value) {
       ......
        mData = value;
        dispatchingValue(null);
    }
    
   
    /**
    * 非UI线程更新持有数据
    **/
    protected void postValue(T value) {
       ......
    }
    
    /**
    * 当observe对象个数从0到1时,被调用
    **/
    protected void onActive() {

    }
    
    
    /**
    * 当observe对象个数从1到0时,被调用
    **/
    protected void onInactive() {

    }    

}

MutableLiveData 类继承于LiveData, 公开暴露postValue,setValue两个方法。

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对象,响应来自所观察LiveData对象的onChanged事件。

public class MediatorLiveData<T> extends MutableLiveData<T> {
    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.
     **/
    @MainThread
    public <S> void addSource(LiveData<S> source, Observer<S> onChanged) {
       ......
    }

    /**
     * Stops to listen the given {@code LiveData}.
     *
    */
    @MainThread
    public <S> void removeSource(LiveData<S> toRemote) {
        ......
    }

    ......
}


参考:
  1. 谷歌官网LiveData
  2. Android 8.1 source code
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容