LiveData笔记

在之前的总结中已经简要介绍了liveData的简单使用,但是咋最近做需求学习前辈的代码的时候发现liveData其实还有一些细节需要比较详细的了解,于是在此做一个总结。

先抄袭一下使用liveData的优点,因为学东西之前总要知道为什么要学

  • 确保UI符合数据状态
    LiveData遵循观察者模式。 当生命周期状态改变时,LiveData会向Observer发出通知。 您可以把更新UI的代码合并在这些Observer对象中。不必去考虑导致数据变化的各个时机,每次数据有变化,Observer都会去更新UI。

  • 没有内存泄漏
    Observer会绑定具有生命周期的对象,并在这个绑定的对象被销毁后自行清理。

  • 不会因停止Activity而发生崩溃
    如果Observer的生命周期处于非活跃状态,例如在后退堆栈中的Activity,就不会收到任何LiveData事件的通知。

  • 不需要手动处理生命周期
    UI组件只需要去观察相关数据,不需要手动去停止或恢复观察。LiveData会进行自动管理这些事情,因为在观察时,它会感知到相应组件的生命周期变化。

  • 始终保持最新的数据
    如果一个对象的生命周期变到非活跃状态,它将在再次变为活跃状态时接收最新的数据。 例如,后台Activity在返回到前台后立即收到最新数据。

  • 正确应对配置更改
    如果一个Activity或Fragment由于配置更改(如设备旋转)而重新创建,它会立即收到最新的可用数据。

  • 共享资源
    您可以使用单例模式扩展LiveData对象并包装成系统服务,以便在应用程序中进行共享。LiveData对象一旦连接到系统服务,任何需要该资源的Observer都只需观察这个LiveData对象。

根据Google官方文档的步骤记录一下官方给的使用方式

Follow these steps to work with LiveData objects:

 1.Create an instance of LiveData to hold a certain type of data. This is usually done within your ViewModel class.
 2.Create an Observer object that defines the onChanged() method, which controls what happens when the LiveData object's held data changes. You usually create an Observer object in a UI controller, such as an activity or fragment.
 3.Attach the Observer object to the LiveData object using the observe() method. The observe() method takes a LifecycleOwner object. This subscribes the Observer object to the LiveData object so that it is notified of changes. You usually attach the Observer object in a UI controller, such as an activity or fragment.
 
 根据官方文档我简单翻译一下
 
 按照以下步骤去使用LiveData对象:

    1.创建一个LiveData用于保存特定类型数据的实例。通常在ViewModel类中声明 。
    2.创建一个Observer(观察者)定义onChanged() 方法,该对象在LiveData对象发生数据更改时进行相应。通常Observer在UI控制器中创建一个对象,例如活动或片段。
    3.使用observe()方法将Observer对象附加到对象。该方法采用一个LifecycleOwner对象。这会将Observer对象绑定到LiveData对象,以便通知其更改。通常绑定对象的过程写在UI控制器中,例如活动或片段。

LiveData的创建

官方代码:

public class NameViewModel extends ViewModel {

    // Create a LiveData with a String
    private MutableLiveData<String> currentName;
    
        public MutableLiveData<String> getCurrentName() {
            if (currentName == null) {
                currentName = new MutableLiveData<String>();
            }
            return currentName;
        }
    
    // Rest of the ViewModel...
}

活动中绑定观察者

public class NameActivity extends AppCompatActivity {

    private NameViewModel model;

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

        // Other code to setup the activity...

        // Get the ViewModel.
        model = 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.
                nameTextView.setText(newName);
            }
        };

        // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
        model.getCurrentName().observe(this, nameObserver);
    }
}

更新LiveData中的数据

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

结合自己的实际项目进行记录

首先先明确两个类

  • MutableLiveData (LiveData子类)

MutableLiveData是LiveData的子类,添加了公共方法setValue和postValue,方便开发者直接使用。setValue必须在主线程调用。postValue可以在后台线程中调用。

  • MediatorLiveData(LiveData子类MutableLiveData的子类)

这个类的点睛之笔就是addSource方法,其实就是它可以观察其他LiveData对象并对它们的OnChanged事件做出反应 。

考虑以下情形:我们有两个实例LiveData,让他们的名字 liveData1和liveData2,我们希望合并他们到一个LiveData对象:liveDataMerger。然后,让liveData1和liveData2同时成为它的源,并且每次onChanged在它们中的任何一个值发生改变时回调,也就是在liveDataMerger中设置新值。

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

然后加一个需求,我们只想要liveData1合并的前10个值合并在liveDataMerger中。然后,在合并10个值之后,我们可以停止收听liveData1,并删除这个源。

     liveDataMerger.addSource(liveData1,new Observer(){
          private int count = 1;
    
          @Override public void onChanged(@Nullable Integer s){
              计数++;
              liveDataMerger.setValue(一个或多个);
              if(count> 10){
                  liveDataMerger.removeSource(liveData1);
              }
          }
     });

可能说起来有点绕,下面会结合实例进行说明。

重点看这个Demo,非常简单但是展现了LiveData的工作过程,因为是自己写的,所以写的不那么高级

在看google官方文档的时候产生了如下问题(我觉得别人也可能会产生同样的问题):

  • observe()方法在添加观察者时,和addSource有啥关系?
  • observe()方法的第二个相应函数有几种写法?有什么注意点?
  • addSource方法的第二个参数和第一个参数的关系?

<b>带着三个问题我写了一个demo</b>

demo的思路:使用两种liveData,想知道liveData_2.addSource(liveData_1,liveData_2::setValue);是不是把第一个参数的值传递给了第二个方法中。传递之后,两个livedata的观察者是否会触发相应

MainActivity.java

public class MainActivity extends AppCompatActivity {
    
    MyViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //用于声明LiveData的ViewModel
        viewModel = new MyViewModel();
        //为LiveData添加相应函数
        viewModel.getLiveData_1().observe(this,this::myObserve1);
        viewModel.getLiveData_2().observe(this,this::myObserve2);
        //用于更新LiveData的值
        List<String> list= new ArrayList<>();
        list.add("第一");
        list.add("第二");
        //调用ViewModel中的方法为LiveData赋值
        viewModel.setLiveData_1(list);
    }

    private void myObserve1(List<String> list) {
        Log.d("MainActivity", "myObserve: LiveData_1 观察者相应");
    }

    private void myObserve2(List<String> list) {
        Log.d("MainActivity", "myObserve: LiveData_2 观察者相应");
    }
}

ViewModel.java

public class MyViewModel {
    MutableLiveData<List<String>>  liveData_1 ;
    MediatorLiveData<List<String>> liveData_2 ;

    public MyViewModel(){
        //实例化两种liveData
        liveData_1 = new MutableLiveData<>();
        liveData_2 = new MediatorLiveData<>();
        //观察liveData_1
        liveData_2.addSource(liveData_1,liveData_2::setValue);
    }

    public void setLiveData_1(List<String> list){
        liveData_1.setValue(list);
    }

    public LiveData<List<String>> getLiveData_1() {
        return liveData_1;
    }

    public MediatorLiveData<List<String>> getLiveData_2() {
        return liveData_2;
    }
}
image.png
image.png

运行后处理问题:

  • observe()方法在添加观察者时,和addSource有啥关系?

    observe方法是响应livedata值的变化,addSource是响应第一个参数值的变化,调用者必须为MediatorLiveData,第一个参数可作为相应方法的参数,一般的作用都是把一个livedata注入到另一个livedata中。

  • observe()方法的第二个相应函数有几种写法?有什么注意点?

    observe可以使用匿名方法直接处理响应,但是为了代码规范最好采用调用的方式,实现的响应函数的参数格式要和livedata的泛型一致

  • addSource方法的第二个参数和第一个参数的关系?

第一个参数可以作为第二个方法的参数,而且注意一点,是jiang
例如:(当livedata1发生变化时,注入到liveData_2)

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

推荐阅读更多精彩内容

  •   LiveData是一个可被观察的数据持有者类。与常规的Observable不同,LiveData能意识到应用程...
    鹤鹤阅读 46,987评论 6 42
  • LiveData是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵...
    tse1y阅读 3,007评论 0 2
  • 概述 LiveData是一个可观察的数据持有者类。 与常规observable不同,LiveData是生命周期感知...
    鹿小纯0831阅读 302评论 0 0
  • 在Model - build.gradle添加依赖 LiveData是一个可观察的数据持有者类。与常规可观察性不同...
    贝贝beibei96阅读 1,410评论 0 1
  • 今天下午,我和姐姐还有奶奶一起出去购物了。 我们到了我们家附近的天启超市,一到超市姐姐就开始“全...
    邓景洋阅读 381评论 0 1