Jetpack(四)—— LiveData

1 简介

以下是LiveData的官网定义:LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services.

从官网的介绍可以看到,LiveData作用跟RxJava类似,是观察数据的类,相比RxJava,它能够在ActivityFragmentService之中正确的处理生命周期。 乍看之下,LiveData挺鸡肋的,事实也确实如此,因为LiveData能够实现的功能RxJava也可以实现,而且与LiveData相比, RxJava拥有着更加丰富的生态,当然,谷歌的官方架构仍然值得我们去学习。

LiveData是一种可观察的数据存储器类,它可以包含任何类型的数据。与常规的可观察类不同,LiveData具有生命周期感知能力,意思是它遵循其它应用组件(如 ActivityFragmentService)的生命周期。这种感知能力可确保LiveData仅更新处于活跃生命周期状态的(应用组件)观察者。

如果观察者的生命周期处于STARTEDRESUMED状态,则LiveData会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者,而非活跃观察者不会收到更改通知。 因此,可以在实现LifecycleOwner接口的类中注册观察者,当相应的Lifecycle对象的状态变为DESTROYED时,便可移除此观察者。 这对于ActivityFragment特别有用,这样它们就可以放心地观察LiveData对象,而不必担心内存泄露(当ActivityFragment的生命周期结束时,系统会立即退订它们)。

使用LiveData具有以下优势:

  • 数据变更的时候更新UI LiveData遵循观察者模式,当数据发生变化时,LiveData会通知Observer对象,可以在这些 Observer 对象中更新界面,无需在每次应用数据发生变化时更新界面,因为观察者会完成更新;
  • 不会发生内存泄漏。 观察者会绑定到Lifecycle对象,并在其关联的生命周期遭到销毁后进行自我清理;
  • 不会因Activity停止而导致崩溃。 如果观察者的生命周期处于非活跃状态(如返回栈中的Activity),它不会接收任何 LiveData事件;
  • 不再需要手动处理生命周期。 界面组件只是观察相关数据,不会停止或恢复观察。LiveData将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化;
  • 数据始终保持最新状态。 如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的Activity会在返回前台后立即接收最新的数据;
  • 适当的配置更改。 如果由于配置更改(如设备旋转)而重新创建了ActivityFragment,它会立即接收最新的可用数据;
  • 共享资源。 可以使用单例模式扩展LiveData对象以封装系统服务,以便在应用中共享它们。LiveData 对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察 LiveData 对象;

LiveData经常与ViewModel在一起使用,虽然它也可以单独用在别的地方,但是在绝大多数情况下,它是使用在ViewModel当中的。

LiveData & ViewModel

LiveDataViewModel在整个MVVM架构中担当数据驱动的职责,这也是MVVM模式中ViewModel层的作用。

为什么不把Activity的实例传给ViewModel呢,这样ViewModel不就能主动对Activity进行通知了吗?这是因为ViewModel的生命周期是长于Activity的,如果把Activity的实例传给ViewModel,就很有可能会因为Activity无法释放而造成内存泄漏,这是一种非常错误的做法。

2 LiveData的基本用法

  1. 创建 LiveData 的实例用来存储某种类型的数据,通常在ViewModel类中完成;
  2. 创建可定义onChanged()方法的Observer对象,该方法可以控制 LiveData 对象存储的数据更改时会发生什么。通常情况下,可以在界面控制器(如ActivityFragment)中创建 Observer 对象;
  3. 使用observe()方法将 Observer 对象附加到 LiveData 对象,observe() 方法会采用LifecycleOwner对象,这样会使 Observer 对象订阅 LiveData 对象,以使其收到有关更改的通知。通常情况下,可以在界面控制器(如ActivityFragment)中附加 Observer 对象;

注意:可以使用observeForever(Observer)方法在没有关联的LifecycleOwner对象的情况下注册一个观察者。在这种情况下,观察者会被视为始终处于活跃状态,因此它始终会收到关于修改的通知。可以通过调用removeObserver(Observer)方法来移除观察者。

它的使用是首先使用LiveData来存储某种类型的数据,这个过程一般是在ViewModel中完成,之后创建Observer对象,Observer接口中只有一个方法onChange(T t),当数据发生变化时就会调用这个方法,一般是在组件,如Activity/Fragment中创建观察者对象;之后调用数据类的observe方法,添加LifecycleOwner对象和observer,这样就可以观察数据的变化了。

当更新存储在 LiveData 对象中的值时,它会触发所有已注册的观察者(只要附加的 LifecycleOwner 处于活跃状态)。LiveData允许界面控制器观察者订阅更新。当LiveData 对象存储的数据发生更改时,界面会自动更新以做出响应。

lifecycle-livedata-ktx就是一个专门为Kotlin语言设计的库,这个库在2.2.0版本中加入了对observe()方法的语法扩展。 我们只需要在app/build.gradle文件中添加如下依赖:

dependencies {
   
   ...
   implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
}
2.1 创建LiveData对象

LiveData是一种可用于任何数据类型的封装容器,其中包括可实现 Collections 的对象,如ListLiveData对象通常存储在ViewModel对象中,并可通过getter方法进行访问, 如以下示例中所示:

class NameViewModel : ViewModel() {
   
    // create a LiveData with a String
    val currentName: MutableLiveData<String> by lazy {
   
        MutableLiveData<String>()
    }
    
    // Rest of the ViewModel
}

注意:请确保用于更新界面的 LiveData 对象存储在 ViewModel 对象中,而不是将其存储在ActivityFragment中,原因如下:避免 ActivityFragment过于庞大。现在,这些界面控制器负责显示数据,但不负责存储数据状态。将 LiveData 实例与特定的ActivityFragment实例分离开,并使 LiveData 对象在配置更改后继续存在。

LiveData常用方法:

LiveData常用方法

MutableLiveData是一种可变的LiveData,它的用法很简单,主要有3种读写数据的方法,分别是getValue()setValue()postValue()方法:

  • getValue()方法用于获取LiveData中包含的数据;
  • setValue()方法用于给LiveData设置数据,但是只能在主线程中调用;
  • postValue()方法用于在非主线程中给LiveData设置数据;

以下是MutableLiveDataLiveData的源码:

public class MutableLiveData<T> extends LiveData<T> {
   
  
    public MutableLiveData(T value) {
    super(value); }
    public MutableLiveData() {
    super(); }

    @Override
    public void postValue(T value) {
    super.postValue(value); }
  
    @Override
    public void setValue(T value) {
    super.setValue(value); }
}

public abstract class LiveData<T> {
   
  
}
2.2 观察LiveData对象

在大多数情况下,应用组件的 onCreate() 方法是开始观察LiveData对象的正确着手点,原因如下:

  • 确保系统不会从ActivityFragmentonResume() 方法进行冗余调用;
  • 确保ActivityFragment变为活跃状态后具有可以立即显示的数据。一旦应用组件处于STARTED状态,就会从它正在观察的 LiveData 对象接收最新值。只有在设置了要观察的 LiveData 对象时,才会发生这种情况;

通常,LiveData仅在数据发生更改时才发送更新,并且仅发送给活跃观察者。此行为的一种例外情况是,观察者从非活跃状态更改为活跃状态时也会收到更新。此外,如果观察者第二次从非活跃状态更改为活跃状态,则只有在自上次变为活跃状态以来值发生了更改时,它才会收到更新。

以下示例代码说明了如何开始观察 LiveData 对象:

class NameActivity : AppCompatActivity() {
   

    private val model: NameViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
   
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_name)

        // Other code to setup the activity

        // Create the observer which updates the UI.
        val nameObserver = Observer<String> {
    newName ->
            // Update the UI, in this case, a TextView.
            nameTextView.text = newName
        }

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

通过调用model.currentName.observe方法来观察数据的变化。任何LiveData对象都可以调用它的observe()方法来观察数据的变化。observe()方法接收两 个参数:第一个参数是一个LifecycleOwner对象,Activity本身就是一个LifecycleOwner对象,因此直接传this就好;第二个参数是一个Observer接口, 当currentName中包含的数据发生变化时,会立即调用Observer.onChanged方法。

以下是Observer的源码:

public interface Observer<T> {
   
    void onChanged(T t);
}

另外,关于LiveData.observe()方法,observe()方法是一个Java方法,如果观察Observer接口,会发现这是一个单抽象方法接口,只有一个待实现的onChanged()方法。因此也可以写成:

model.currentName.observe(this) {
    newName ->
      nameTextView.text = newName
}
2.3 更新 LiveData 对象

LiveData没有公开可用的方法来更新存储的数据。MutableLiveData类将公开setValue(T)postValue(T)方法,如果需要修改存储在LiveData对象中的值,则必须使用这些方法。通常情况下会在ViewModel中使用 MutableLiveData,然后 ViewModel 只会向观察者公开不可变的 LiveData 对象。

设置观察者关系后,可以更新 LiveData 对象的值(如以下示例中所示),这样当用户点按某个按钮时会触发所有观察者:

button.setOnClickListener {
   
  val anotherName = "John Doe"
  model.currentName.value = anotherName
}

在本示例中调用 setValue(T) 导致观察者使用值 John Doe 调用其onChanged()方法。本示例中演示的是按下按钮的方法,但也可以出于各种各样的原因调用 setValue()postValue() 来更新 mName,这些原因包括响应网络请求或数据库加载完成。在所有情况下,调用 setValue()postValue() 都会触发观察者并更新界面。

注意:必须调用setValue(T)方法以从主线程更新 LiveData 对象。如果在工作器线程中执行代码,可以改用postValue(T)方法来更新 LiveData 对象。

3 LiveData的源码分析

3.1 LiveData.observe(LifecyleOwner owner, Observer<? super T> observer)

obsever方法中传入了两个参数,一个是LifecycleOwner,一个是Observer。**Observer是观察者,它是一个单一方法接口,当数据发生变化时,会回调onChange(T t)方法,**以下是相关源码:

public interface Observer<T> {
   
      /**
       * Called when the data is changed.
       * @param t  The new data
       */
      void onChanged(T t);
}

之后来看observe方法的具体实现,以下是源码:

public abstract class LiveData<T> {
   
  
  private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
   
      	// 1. 只能在主线程中调用observe方法
        assertMainThread("observe");
        // 	2. 当Lifecycle.State == DESTROYED时,订阅观察者时没有意义的,直接返回
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
   
          return;
        }
      	// 3. LifeycleBoundObserver最终是LifecycleObserver的实现类
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
      	// 4. observer作为key,wrap
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值