LiveData特性与数据丢失问题或异常问题解析

LiveData

  • 基本特性

    1.没有内存泄漏:因为 Observer被绑定到它们自己的 Lifecycle对象上,所以,当它们的 Lifecycle 被销毁时,它们能自动的被清理。

    2.不会因为 Activity 停止而崩溃:如果 Observer 的 Lifecycle 处于闲置状态(例如:activity 在后台时),它们不会收到变更事件。

    3.始终保持数据最新:如果 Lifecycle重新启动(例如:activity 从后台返回到启动状态)将会收到最新的位置数据(前提是有新数据更新,或者被重新订阅)。

    4.正确处理配置更改:如果 activity 或 fragment 由于配置更改(如:设备旋转)重新创建,将会立即收到最新的有效位置数据。

    5.资源共享:可以只保留一个 MyLocationListener 实例,只连接系统服务一次,并且能够正确的支持应用程序中的所有观察者。

    6.不再手动管理生命周期你可能已经注意到,fragment 只是在需要的时候观察数据,不用担心被停止或者在停止之后启动观察。由于 fragment 在观察数据时提供了其 Lifecycle,所以 LiveData会自动管理这一切。

  • 基本用法

/**

  • ViewModel
    **/
    public class SampleViewModel extends ViewModel {
    private MutableLiveData<String> sampleLiveData;
    public MutableLiveData<String> getSampleLiveData() {
    if (sampleLiveData == null) {
    sampleLiveData = new MutableLiveData<String>();
    }
    return sampleLiveData;
    }
//主线程更新数据调用
sampleLiveData.setValue(data);

//子线程更新数据调用
sampleLiveData.postValue(data);

}
/**

  • Activity
    /
    public class SampleActivity extends AppCompatActivity {
    private SampleViewModel viewModel;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    viewModel = ViewModelProviders.of(this).get(SampleViewModel.class);
    final Observer<String> observer = new Observer<String>() {
    @Override
    public void onChanged(@Nullable final String dataStr) {
    textView.setText(dataStr);
    }
    };
    viewModel.getSampleLiveData().observe(this, observer);
    }
    }
    /
  • Fragment
    **/
    public class SampleFragment extends Fragment {
    private SampleViewModel viewModel;
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    viewModel = ViewModelProviders.of(this).get(SampleViewModel.class);
    final Observer<String> observer = new Observer<String>() {
    @Override
    public void onChanged(@Nullable final String dataStr) {
    textView.setText(dataStr);
    }
    };
    viewModel.getSampleLiveData().observe(this, observer);
    }
    }
    Note: 确保 LiveData 是在ViewModel 中更新数据,原因如下:

避免Activity和Fragment变的臃肿。这样UI只需要关心它需要展示的数据,而不需要关系数据的获取和状态。
抽离LiveData到ViewModel 中可以使Activity和Fragment在重建之后数据不会丢失。

observeForever

viewModel.getSampleLiveData().observeForever(observer);
viewModel.getSampleLiveData().removeObserver(observer);

自定义LiveData

public class CustomLiveData extends LiveData<String> {
/**
* 有可被通知的observer
/
@Override
protected void onActive() {
super.onActive();
}
/
*
* 没有可被通知的observer
*/
@Override
protected void onInactive() {
super.onInactive();
}
}

MediatorLiveData

private MutableLiveData<String> data1 = new MutableLiveData<>();
private MutableLiveData<String> data2 = new MutableLiveData<>();
private MediatorLiveData<String> mediatorLiveData = new MediatorLiveData<>();
private void sample(@NonNull LifecycleOwner owner) {
    mediatorLiveData.addSource(data1, new Observer<String>() {
        @Override
        public void onChanged(@Nullable String s) {
            mediatorLiveData.setValue(s);
        }
    });
    mediatorLiveData.addSource(data2, new Observer<String>() {
        @Override
        public void onChanged(@Nullable String s) {
            mediatorLiveData.setValue(s);
        }
    });
    
    mediatorLiveData.observe(owner, new Observer<String>() {
        @Override
        public void onChanged(@Nullable String s) {
        }
    });
    // mediatorLiveData.removeSource();
}

关于更新数据丢失问题

在UI可见时,调用
liveData.postValue("a");
liveData.setValue("b");
会先收到"b",后收到"a"

在UI不可见时,调用
liveData.postValue("a");
liveData.setValue("b");
当UI可见,只会收到"a",因为setValue先执行,之后被postValue更新掉

在UI可见时,调用
liveData.setValue("a");
liveData.setValue("b");
liveData.setValue("c");
liveData.setValue("d");
liveData.setValue("e");
会按顺序收到"a","b","c","d","e"

在UI可见时,调用
liveData.postValue("a");
liveData.postValue("b");
liveData.postValue("c");
liveData.postValue("d");
liveData.postValue("e");
只会收到"e"

在UI可见时,调用
liveData.postValue("a");
liveData.postValue("b");
liveData.postValue("c");
liveData.postValue("d");
liveData.setValue("e");
会先收到"e",后收到"d"

在UI不可见时,调用
liveData.setValue("a");
liveData.setValue("b");
liveData.setValue("c");
liveData.setValue("d");
liveData.setValue("e");
当UI可见之后,只会收到"e"

在UI不可见时,调用
liveData.postValue("a");
liveData.postValue("b");
liveData.postValue("c");
liveData.postValue("d");
liveData.postValue("e");
当UI可见之后,只会收到"e"

在UI不可见时,调用
liveData.setValue("a");
liveData.setValue("b");
liveData.setValue("c");
liveData.setValue("d");
liveData.postValue("e");
当UI可见之后,只会收到"e"

在UI不可见时,调用
liveData.postValue("a");
liveData.postValue("b");
liveData.postValue("c");
liveData.postValue("d");
liveData.setValue("e");
当UI可见之后,只会收到"d"

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

推荐阅读更多精彩内容