livedata_关于livedata应该了解的一切

livedata

重点 (Top highlight)

Architecture components are common for Android developers these days. For a long time, everyone has been using one or other architecture components to meet their requirements. LiveData is one of the most important of these components. In this piece, we discuss LiveData, how it’s used, and its importance.

如今,架构组件对于Android开发人员来说很常见。 长期以来,每个人都在使用一个或其他体系结构组件来满足他们的要求。 LiveData是这些组件中最重要的组件。 在本文中,我们讨论了LiveData,如何使用它以及它的重要性。

Image for post

问题 (Problem)

Previously before architecture components and Rx Java do you remember how we passed the results or callbacks to the UI thread? Primarily, with interfaces.

以前,在体系结构组件和Rx Java之前,您还记得我们如何将结果或回调传递给UI thread吗? 主要是带有接口的。

Let’s take a simple example of an application developed in MVP. Previously, if there was an API call to be performed, we would call a method from View layer in the Presenter to perform a network request. Then, in that particular method, we used to write the Async task to perform the operations. Once we receive the response we used a View interface to communicate this response to the Main thread so that it could update the UI.

让我们举一个用MVP开发的应用程序的简单示例。 以前,如果要执行API调用,我们将从Presenter View层调用一个方法来执行网络请求。 然后,在该特定方法中,我们习惯于编写Async task来执行操作。 收到响应后,我们将使用View界面将此响应传达给Main线程,以便它可以更新UI。

Here everything is tightly coupled View and Presenter and a huge number of interfaces are used for interaction between layers.

在这里,所有东西都紧密地结合在View和Presenter上,并且大量的接口用于图层之间的交互。

(Solution)

The solution to this came with MVVM, but we’re not going to discuss this here. Suffice it to say that the major issue of using the interfaces has been solved by the concept of LiveData.

MVVM解决方案,但我们不在这里讨论。 可以说,使用interfaces的主要问题已由LiveData概念解决。

什么是LiveData? (What is LiveData?)

From the documentation:

从文档中:

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. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.

LiveData可观察的数据持有者类。 与常规的可观察对象不同,LiveData具有生命周期感知功能 ,这意味着它尊重其他应用程序组件(例如活动,片段或服务)的生命周期。 这种意识确保LiveData仅更新处于活动生命周期状态的应用程序组件观察者。

它是如何工作的? (How does it work?)

To understand LiveData first we need to understand Observer Pattern. The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.

要首先了解LiveData,我们需要了解观察者模式。 observer pattern是一种软件设计模式,其中一个称为主题的对象会维护其依赖者的列表(称为观察者),并通常通过调用其方法之一来自动将状态更改通知他们。

In simple terms, there will be an Observer that subscribes to the Observable to get notified for the latest data or say state changes. Previously we used Rx Java but here we need to maintain a list of subscriptions and remove them in onDestroy().

简单来说,会有一个Observer ,订阅的Observable 以获得有关最新数据的通知或说状态更改。 以前我们使用Rx Java但在这里我们需要维护一个subscriptions列表,并在onDestroy()中将其remove

The main concept of LiveData is an Observer pattern. LiveData is an observable data holder class — there’s no need to request the latest data every time. While using MVVM the communication from ViewModel to View is done with just LiveData.

LiveData主要概念是Observer模式。 LiveData是一个observable数据持有者类-无需每次都请求最新数据。 使用MVVM ,仅使用LiveData完成从ViewModelView的通信。

From the View activity or fragment we subscribe to the LiveData, passing the lifecycle owner and Observer. But there’s no need to maintain the list or destroy the subscriptions. As LiveData is lifecycle-aware it takes care of these things.

View活动或片段中,我们subscribe LiveData 通过lifecycle owner Observer 。 但是,无需维护列表或破坏订阅。 由于LiveData具有lifecycle-aware 它会照顾这些事情。

LiveData only posts the values to Observers (activity or Fragment) if they are in a foreground state, so that no memory leaks occur. There’s no need for us to check whether View is alive or not to update the UI inside the Observer.

LiveData仅在Observers (活动或片段)处于foreground状态时才将其发布,这样就不会发生内存泄漏。 无需检查View是否处于alive来更新Observer的UI。

We no longer need to worry about unsubscribing it onPause or onDestroy. Besides, once the Observer is resumed, it would be immediately be notified of the latest data from the LiveData.

我们不再需要担心在onPauseonDestroy取消订阅它。 此外,一旦Observer恢复,将立即从LiveData收到最新数据的LiveData

Image for post

The two important things that we need to understand about LiveData are

关于LiveData ,我们需要了解的两个重要事项是

  • UI controller or View (an Activity or Fragment) will be notified every time the data changes instead of requesting the data each time from ViewModel (Always up to date data!)

    每次数据更改时都会通知UI控制器或View(一个ActivityFragment ),而不是每次都从ViewModel请求数据( 始终是最新数据 !)

  • LiveData is lifecycle-aware, so the view will be registered for observing those changes only if the View (an Activity or Fragment) is in STARTED or RESUMED state and only then the LiveData will emit any items (so there will be no more crashes, lifecycle handling, memory leaks and NullPointerExceptions due to unexisting views!)

    LiveData是lifecycle-aware ,所以视图将被注册用于观察这些变化仅当View (一个ActivityFragment )是STARTEDRESUMED状态才把LiveData将发射的任何项目(因此将不会有更多的崩溃,生命周期处理,内存泄漏和由于不存在的视图而导致的NullPointerExceptions !)

让我们开始编码 (Let's Start Coding)

To work with LiveData we need to take the following steps:

要使用LiveData我们需要执行以下步骤:

  • Declare dependencies in the app level build.gradle.

    在应用程序级别build.gradle声明依赖build.gradle

  • Create an instance of LiveData to hold a certain type of data. This is usually done inside ViewModel class.

    创建LiveData instance以保存某种类型的数据。 这通常是在ViewModel类中完成的。

  • 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.

    创建一个定义onChanged()方法的Observer对象,该方法控制LiveData对象的保留数据更改时发生的情况。 通常,您可以在UI控制器中创建一个Observer对象,例如活动或片段。

  • Attach the Observer object to the LiveData object using the observe() method. This method takes a LifecycleOwner object and subscribes Observer object to the LiveData object so that it’s notified of changes. You usually attach the Observer object in a UI controller, such as an activity or fragment.

    使用observe()方法将Observer对象附加到LiveData对象。 此方法采用LifecycleOwner对象,并将Observer对象订阅到LiveData对象,以便将更改通知给它。 通常,您将Observer对象附加到UI控制器中,例如activityfragment

声明依赖 (Declare dependencies)

//Java
implementation "android.arch.lifecycle:extensions:1.0.0"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0"//Kotlin with AndroidX
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'

创建LiveData实例 (Creating LiveData instance)

LiveData is a wrapper that can be used to hold any type of data, including objects that implement Collections, such as List. A LiveData object is usually stored within a ViewModel object and is accessed using a getter method.

LiveData是一个包装器,可用于保存任何类型的数据,包括实现Collection的对象,如ListLiveData对象通常存储在ViewModel对象中,并使用getter方法进行访问。

Initially, the data in a LiveData object is not set later when we call setFirstName() then the value of LiveData was updated.

最初,当我们调用setFirstName()时,不会设置LiveData对象中的数据,然后更新LiveData的值。

在UI控制器中为LiveData创建观察者 (Creating an Observer for LiveData in UI controller)

Create an Activity and observe the LiveData for any changes as shown below

创建一个Activity并观察LiveData的任何变化,如下所示

更新LiveData值 (Update LiveData Values)

There are two ways to update a value in LiveData.

有两种方法可以更新LiveData中的值。

  • setValue

    setValue

  • postValue

    postValue

设定值 (setValue)

We must use the setValue(T) method to update the LiveData object from the main thread. If we use setValue from background thread then the app crashes, logging called from WongThread exception.

我们必须使用setValue(T)方法从main thread更新LiveData对象。 如果我们使用setValue 从后台线程启动,然后应用程序崩溃,并从WongThread异常调用日志记录。

_nameLiveData.value = "something"

后值 (postValue)

If the code is executed in a worker thread, other than the main thread, you can use the postValue(T) method to update the LiveData object. It can be used from any thread but preferred is from other than main thread because it’s a bit slower than setValue.

如果代码是在worker线程(而不是主线程)中执行的,则可以使用postValue(T)方法更新LiveData对象。 可以在任何线程中使用它,但首选从主线程之外的其他线程使用,因为它比setValue慢一些。

_nameLiveData.postValue("something")

To update the LiveData value use setValue from Main Thread and postValue from any other thread other than the main thread for better performance.

要更新LiveData值,请使用 setValue Main Thread 后值 从任何其他 thread 主线程以外的其他线程以获得更好的性能。

用例 (Use case)

Say there’s an app that has to make an API call when a user opens an activity and clicks a button. After getting the response with LiveData, we post the value to the UI controller to update the view. In this case, while the API call is in progress, somehow the app goes into the background state. Can you guess what happens next? Will the UI update or will the app crash?

假设有一个应用程序在用户打开活动并单击按钮时必须进行API调用。 使用LiveData获得响应后,我们将该值发布到UI控制器以更新视图。 在这种情况下,当API调用progress ,应用程序将以某种方式进入background状态。 你能猜出接下来会发生什么吗? 用户界面会更新还是应用崩溃?

The API call gets completed and LiveData receives the value. However, neither the crash or the UI is updated because, as we discussed above, LiveData is lifecycle-aware so when the API call is finished the LiveData receives the value but it doesn’t post the value to the UI controller. It will wait until the UI controller comes to foreground state and then LiveData immediately posts the latest available value to the UI controller.

API调用完成, LiveData接收该值。 但是,崩溃或UI均未更新,因为如上所述,LiveData可lifecycle-aware 所以 当API调用完成后,LiveData会收到该值,但不会将该值发布到UI控制器。 它将等到UI控制器进入foreground状态,然后LiveData立即将最新的可用值发布到UI控制器。

LiveData的类型 (Types of LiveData)

We can extend LiveData<T> and create our own custom class.

我们可以扩展LiveData<T> 并创建我们自己的自定义类。

MutableLiveData (MutableLiveData)

Code of MutableLiveData, as per the documentation:

MutableLiveData代码,根据文档:

MediatorLiveData (MediatorLiveData)

Image for post

We can merge results from different LiveData objects into one using MediatorLiveData. It can also be defined as the LiveData subclass, which may observe other LiveData objects and react to OnChanged events from them.

我们可以使用MediatorLiveData将来自不同LiveData对象的结果合并为一个。 也可以将其定义为LiveData子类,该子类可以观察其他LiveData对象并对其中的OnChanged事件做出React。

Suppose we have two LiveData objects emitting the number type value. One LiveData object emits values from a particular source and the other from a different source. We want to listen to the result from both of them and also want to neglect the result from the second LiveData if it is less than ten. We do this as follows:

假设我们有两个LiveData对象发出数字类型值。 一个LiveData对象从特定来源发出值,而另一个从另一个来源发出值。 我们想要听取他们两个的结果,并且还想忽略第二个LiveData的结果(如果小于十个)。 我们这样做如下:

val mediatorLiveData: MediatorLiveData<Int> = MediatorLiveData()
mediatorLiveData.addSource(stockLiveData1, Observer<Int> { it ->
mediatorLiveData.setValue(it)})
mediatorLiveData.addSource(stockLiveData1, Observer<Int> { value ->if (value > 10) {
mediatorLiveData.setValue(value)
}})

用例 (Use case)

Let’s say that we only want five values emitted by liveData, to be merged inMediatorLiveData. Then, after those five values, we can stop listening to liveData and remove it as a source:

假设我们只希望将liveData发出的五个值合并到MediatorLiveData 。 然后,在这五个值之后,我们可以停止监听liveData并将其作为源删除:

val liveDataMerger: MediatorLiveData<Int> = MediatorLiveData()
val liveData = MutableLiveData<Int>()
val liveData2 = MutableLiveData<Int>()
liveDataMerger.addSource(liveData) { value ->liveDataMerger.setValue(value)}liveDataMerger.addSource(liveData2) { value2->var count = 1
count++
liveDataMerger.setValue(value2)
if (count > 5) {
liveDataMerger.removeSource(liveData2)
}}

If the given LiveData is already added as a source but with a different Observer, then IllegalArgumentException will be thrown.

如果给定的 LiveData 已作为源添加,但具有不同的 Observer ,则将 IllegalArgumentException

转变 (Transformations)

The Transformations class provides us with functions with which we can change the value in our LiveData object. Currently, we have 2 functions available in this class: map and switchMap.

Transformations类为我们提供了一些函数,通过这些函数可以更改LiveData对象中的值。 当前,我们在此类中提供2个功能: mapswitchMap

map() allows you to apply changes to each value as they’re emitted by LiveData.This method is analogous to the Rx(io.reactivex.Observable) map operator. The transform will be executed on the main thread. Here is an example from the docs where a User object is mapped to get the compete name:

map()允许您将更改应用于LiveData发出的每个值。 此方法类似于 Rx(io.reactivex.Observable) 映射运算符。 转换将在 main 线程 上执行 这是来自docs的示例,其中映射了User对象以获取竞争名称:

LiveData<User> userLiveData = ...;LiveData<String> userFullNameLiveData =
Transformations.map(userLiveData,user ->
user.firstName + user.lastName);
});

As per documentation, the map method code is as follows:

根据文档, map 方法代码如下:

@MainThread
public static <X, Y> LiveData<Y> map(
@NonNull LiveData<X> source,
@NonNull final Function<X, Y> mapFunction) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
@Override
public void onChanged(@Nullable X x) {
result.setValue(mapFunction.apply(x));
}
});
return result;
}

switchMap returns a new LiveData object rather than a value, i.e. it switches the actual LiveData for a new one. This method is analogous to the Rx(io.reactivex.Observable) switchMap operator. switchMapFunction will be executed on the main thread.

switchMap返回一个新的LiveData对象而不是一个值,即,它将实际的LiveData切换为一个新的LiveData对象。 此方法类似于 Rx(io.reactivex.Observable) switchMap运算符。 switchMapFunction 将在 main 线程 上执行

Here is an example class that holds a typed-in name of a user which is String from an EditTex in a MutableLiveData and returns a LiveData containing a list of user objects for users that have the same name. It populates that LiveData by re-querying a repository-pattern object each time the typed name changes.

这里是保存的示例类一个键入的是字符串从一个用户的名称EditTexMutableLiveData并返回一个LiveData包含该具有相同的名称的用户的用户对象的列表。 每次键入的名称更改时,它LiveData通过重新查询存储库模式对象来填充LiveData

 class UserViewModel extends AndroidViewModel {
MutableLiveData<String> nameQueryLiveData = ...
LiveData<List<String>> getUsersWithNameLiveData() {
return Transformations.switchMap(
nameQueryLiveData,
name -> myDataSource.getUsersWithNameLiveData(name));
}
void setNameQuery(String name) {
this.nameQueryLiveData.setValue(name);
}
}

As per documentation, switchMap method code is as follows:

根据文档, switchMap 方法代码如下:

Please give me your suggestions and comments.

请给我您的建议和意见。

Thanks for reading!

谢谢阅读!

翻译自: https://medium.com/better-programming/everything-to-should-understand-about-livedata-507dd83adea7

livedata

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值