AAC---LiveData

LiveData

LiveData是一个与Activity/Fragment生命周期相关(lifecycle-aware)的Observer类。而这种相关性(awareness )会导致LiveData中的数据只有在Active状态下才会被回调。

我们可以通过实现了LifeCycleOwner接口的对象来提供生命周期的感知。而LiveData这种方式会使得不用再考虑Activity或者Fragment的泄露,当生命周期结束时,会自动销毁Observer对象。

使用LiveData的好处

  • 保证UI与数据状态同步
    LiveData使用Observer模式,只有当Lifecycle的状态改变时候,才会回调给Observer。
  • 没有内存泄漏
    Observer绑定了Lifecycle,并且在关联的LifeCycle被销毁时,将Observer清除
  • 没有因为Activity Stop导致的Crash
    当Lifecycle处于inactive状态时,例如一个Activity回退到Activity栈中,就不会受到任何LiveData的事件了
  • 不用再手动管理生命周期
    UI组件只需要关心数据,而不用在onResume、onStop等回调函数中处理
  • 始终保持最新数据
    当LifeCycle变成inactive状态时,它接收最新的数据,当LifeCycle再次变成active状态,会将最新的数据回调。比如在后台一个Activity收到了最新的数据,而当它回到前台时候,则会将数据回调。
  • 合理的Configuration改变
    旋转时候,它会立马接收到最新的可用数据,而不会因为重新创建Activity而重新创建
  • 共享资源
    可以通过继承一个LiveData对象,并且使用单例模式来封装一个系统的Service,以至于它可以在App内共享。LiveData对象一旦连接系统Service,当有Observer需要资源的话,就可以监听LiveData对象了

使用方法

  1. build.gradle中添加配置
dependencies {
    def lifecycle_version = "1.1.1"

    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    // alternatively - just ViewModel
    implementation "android.arch.lifecycle:viewmodel:$lifecycle_version" // use -ktx for Kotlin
    // alternatively - just LiveData
    implementation "android.arch.lifecycle:livedata:$lifecycle_version"
    // alternatively - Lifecycles only (no ViewModel or LiveData).
    //     Support library depends on this lightweight import
    implementation "android.arch.lifecycle:runtime:$lifecycle_version"

    annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
    // alternately - if using Java8, use the following instead of compiler
    implementation "android.arch.lifecycle:common-java8:$lifecycle_version"

    // optional - ReactiveStreams support for LiveData
    implementation "android.arch.lifecycle:reactivestreams:$lifecycle_version"

    // optional - Test helpers for LiveData
    testImplementation "android.arch.core:core-testing:$lifecycle_version"
}
  1. 创建与LifeCycleOwner相关联的LiveData对象
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        MutableLiveData<UserData> liveData = new MutableLiveData<>();
        liveData.observe(this, new Observer<UserData>() {
            @Override public void onChanged(@Nullable UserData userData) {
                // TODO:
            }
        });
    }

}
  1. LiveData中的数据有变化时候,则可以调用setValue或者在非主线程中调用postValue改变,而修改后的值会通过onChanged方法回调。
liveData.setValue(new UserData());
liveData.postValue(new UserData());

MutableLiveData与MediatorLiveData

  • MutableLiveData:可变的LiveData
    普通的LiveData将setValue以及postValue的作用于定义成protected,除非继承LiveData否则访问这两个函数。而MutableLiveData只是Override这两个函数,将protected作用域扩大成了public,以至于外部可以访问。
  • MediatorLiveData:多来源的LiveData
    它可以对一个数据结构添加多个数据来源,addSource函数添加LiveData类型的数据来源,而后回调给MediatorLiveData达到多路数据源的效果。比如同一种数据,来自网络与文件缓存。
MutableLiveData<UserData> localCache = new MutableLiveData<>();
localCache.observe(this, userData -> {
            // TODO:
        });
MutableLiveData<UserData> networkData = new MutableLiveData<>();
networkData.observe(this, userData -> {
            // TODO:
        });
MediatorLiveData<String> live1 = new MediatorLiveData<>();
live1.addSource(localCache, userData -> live1.setValue(userData.getUserName()));
live1.addSource(networkData, userData -> live1.setValue(userData.getUserName()));

与Room与ViewModel组件相辅相成

  • Room:
    Room中Query返回的对象可以是一个LiveData,而当数据库中数据有改变时,该LiveData也会收到最新的数据
  • ViewModel:
    ViewModel的作用也就是请求数据,或者做一些前台耗时操作,当数据返回或者操作完成后,通过LiveData回调给UI Controller修改UI

继承LiveData

通过继承LiveData类重写onActive以及onInactive函数来完成对数据请求/前台耗时操作的回调等等

public class StockLiveData extends LiveData<BigDecimal> {
    private StockManager mStockManager;

    private SimplePriceListener mListener = new SimplePriceListener() {
        @Override
        public void onPriceChanged(BigDecimal price) {
            setValue(price);
        }
    };

    public StockLiveData(String symbol) {
        mStockManager = new StockManager(symbol);
    }

    @Override
    protected void onActive() {
        mStockManager.requestPriceUpdates(mListener);
    }

    @Override
    protected void onInactive() {
        mStockManager.removeUpdates(mListener);
    }
}

以下为当使用单例LiveData时的情况

public class StockLiveData extends LiveData<BigDecimal> {
    private static StockLiveData sInstance;
    private StockManager mStockManager;

    private SimplePriceListener mListener = new SimplePriceListener() {
        @Override
        public void onPriceChanged(BigDecimal price) {
            setValue(price);
        }
    };

    @MainThread
    public static StockLiveData get(String symbol) {
        if (sInstance == null) {
            sInstance = new StockLiveData(symbol);
        }
        return sInstance;
    }

    private StockLiveData(String symbol) {
        mStockManager = new StockManager(symbol);
    }

    @Override
    protected void onActive() {
        mStockManager.requestPriceUpdates(mListener);
    }

    @Override
    protected void onInactive() {
        mStockManager.removeUpdates(mListener);
    }
}

Transformations

主要为了在数据(Value)分发前,修改分发的值。

  • Transformations.map
LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
    user.name + " " + user.lastName
});
  • Transformations.switchMap
private LiveData<User> getUser(String id) {
  ...;
}
LiveData<String> userId = ...;
LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );

参考资料

LiveData

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

推荐阅读更多精彩内容