Android Jetpack 之 LiveData

简介:
 LiveData 是一个有生命周期感知 & 可观察数据持有者类。
作用:
持久化的观察数据的更改和变化。
特点:
1、感知对应的Activity的生命周期,只有生命周期处于onStart、onResume时,LiveData处于活动状态,
才会把更新的数据通知至对应的Activity。
2、当生命周期处于onStop 或 onPause 时,不回调数据更新,直至处于onResume时才会回调。
3、当生命周期处于onDestroy 时,观察者会自动退出,防止内存泄漏。

个人理解:
我们工作中,大部分应用会从网络或数据库存取数据,并根据数据更新数据,为了避免ANR,主线程中不能存取数据。
而后台线程中无法更新界面,通常我们的做法是让后台线程将数据通过Handler传递给主线程。但是当我们
页面逻辑复杂时,使用Handler这种方式会变的尤为麻烦,为了简化界面更新的工作,Google就为我们提供了
LiveData组件。

用法:
当我们得到数据后,通过 postValue() 投递数据,其他线程通过 getValue() 得到数据。为了通知其他线程,
LiveData采用观察者模式,通过observe()方法,其他线程可以在数据更新后立即得到通知。
我们先来一个简单的例子看看怎么使用。

如果是低版本的项目的话需要添加依赖:

implementation "android.arch.lifecycle:livedata:1.1.1"

我的话项目版本比较高,不需要添加,livedata包含在android.arch.lifecycle中,插一句,Lifecycle 组件包括LifecycleOwner、LifecycleObserver。Lifecycle 组件是执行操作以响应另一个组件(Activity或者Fragment)的生命周期状态的更改。 Lifecycle 生成更易于组织、更轻量级,更易于维护的代码。

上代码,首先是我们的bean类:

public class Person extends BaseObservable {
    private String name;
    private String sex;

    @Bindable
    public String getName() {
        return name;
    }


    @Bindable
    public String getSex() {
        return sex;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

接下来是我们简单的页面布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        android:layout_gravity="center"
        />
    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="请求"/>

</LinearLayout>

然后就是我们的页面代码:

public class LiveDataActivity extends AppCompatActivity {
    private TextView tv;
    private Button btn;
    private MutableLiveData<Person> personLD = new MutableLiveData<>();
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_livedata);
        tv = findViewById(R.id.tv);
        btn = findViewById(R.id.btn);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //模拟网络请求
                try {
                    Thread.sleep(3000);
                    Person person = new Person();
                    person.setName("白展堂");
                    person.setSex("男");
                    personLD.postValue(person);//设置数据
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        personLD.observe(this, new Observer<Person>() {//通过observe监听数据的变化
            @Override
            public void onChanged(@Nullable Person person) {
                tv.setText("name:"+person.getName() +" sex: "+ person.getSex());//数据变化时更新页面
            }
        });
    }
}

注:MutableLiveData  是  LiveData的一个实现类,它的直接父类是LiveData。

我们可以看到,observe()方法有两个参数,第一个参数的类型是LifecycleOwner,加入LifecycleOwner的目的是自动管理Activity生命周期。第二个参数是观察者。

到这里数据就可以正常显示了。

当我这里点击请求按钮的时候,马上退到桌面后台,即页面不可见的时候,虽然 postValue() 方法已执行,但是当页面不可见时,observer里面的 onChanged()是没有执行的,只有当我们重新打开这页面的时候,这个更新数据的方法才会执行。我们可以接着往下看。

实际上,LiveData的数据传递也是通过Handler传递的,在postValue方法的源码可以看到,,LiveData调用ArchTaskExecutor.postToMainThread(),将一个Runnable对象传递给主线程。这个Runnable对象调用setValue()对数据进行更新。当我们更新数据的时候,LiveData第一步是将版本号加1,第二步是遍历观察者。如果观察者处于活跃状态(Lifecycle.State是STARTED或RESUMED),并且观察者的版本号小于LiveData,LiveData会调用观察者的onChanged()方法进行通知。这个就是我们上面问题的原因。

当观察者的生命周期不是STARTED或RESUMED时,数据更新不会进行通知。它的实现方法是在我们调用observe()方法时,

我们第一个参数是LifecycleOwner,第二个参数是Observer。LiveData内部建立了一个LifecyleBoundObserver对象,它将我们传的参数绑定到了一起,用来接收Lifecycle的生命周期更新和LiveData的数据更新,LifecyleBoundObserver是LiveData的内部类,持有LiveData的引用,当生命周期发生变化时,LifecyleBoundObserver会调用LiveData的dispatchingValue()方法,获取最新数据进行更新。

日常工作中,我们使用LiveData通常是配合其他框架一起使用,一个是Room,一个是ViewModel,这两个都是Android Jetpack生态下的框架。

Room是Jetpack提供的SQLite 工具,它读取数据的方法都是阻塞的,要在后台子线程执行,所以非常适合与LiveData配合使用,据我了解Room定义的Dao支持返回LiveData(没用过),当我们查询数据库返回后,可以对界面进行更新。

 

ViewModel可以用来管理Activity或Fragment中的各个LiveData对象。可以把ViewModel看成是LiveData的集合。
ViewModel的作用是可以和Activity或Fragment绑定在一起,并且在配置改变引起的Activity/Fragment销毁时,ViewModel仍然可以持有状态。

今天就写到这里吧。共勉

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值