欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android Jetpack 之 LiveData

程序员文章站 2022-06-09 23:34:33
...

简介:
 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生命周期。第二个参数是观察者。

Android Jetpack 之 LiveData

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

当我这里点击请求按钮的时候,马上退到桌面后台,即页面不可见的时候,虽然 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仍然可以持有状态。

今天就写到这里吧。共勉