livedata_探索LiveData和Kotlin流

方野
2023-12-01

livedata

摘掉这篇文章 (Take away from this article)

In this article, you’ll learn what and how to use Livedata & Kotlin flow. The key differences between them and a real-time example demonstrating the appropriate usage.

在本文中,您将学习如何使用Livedata和Kotlin流。 它们之间的主要区别和一个实时示例演示了适当的用法。

介绍 (Introduction)

LiveData is the means to transfer data, which is a common task in mobile development. Kotlin flow also has the ability to transfer data in a unique way and also perform async operations. Both have there limitations and advantages. They are designed to use in specific use-cases to overcome traditional problems.

LiveData是传输数据的方法,这是移动开发中的常见任务。 Kotlin流还具有以独特的方式传输数据并执行异步操作的能力。 两者都有局限性和优势。 它们旨在用于特定用例中以克服传统问题。

什么是LiveData? (What is LiveData?)

In simple terms, Live data is an observable data holder class — meaning livedata can hold a set of data that can be observed from other android components like activities, fragments and services.

简而言之,实时数据是一个可观察的数据持有者类,这意味着实时数据可以保存一组可以从其他Android组件(例如活动,片段和服务)观察到的数据。

Live data is lifecycle aware — once the component which is observing data is destroyed or not active, livedata stops publishing data to that observer. This solves many conventional problems for Android developers.

实时数据是生命周期感知的-观察数据的组件被破坏或不活动时,实时数据将停止向该观察者发布数据。 这为Android开发人员解决了许多常规问题。

Most of the developers use livedata in MVVM Architecture to communicate or transmit data from the ViewModel to view. This ensures a lifecycle aware communication between them by reducing memory leaks.

大多数开发人员使用MVVM体系结构中的实时数据来通信或传输ViewModel进行查看的数据。 这样可以通过减少内存泄漏来确保它们之间的生命周期感知通信。

Advantages of using LiveData:

使用LiveData的优势:

  • No memory leaks

    没有内存泄漏
  • No crashes due to stopped components

    没有因组件停止而导致的崩溃
  • No more manually lifecycle handling

    不再需要手动进行生命周期处理
  • Resource sharing

    资源共享

如何使用LiveData? (How to use LiveData?)

Let’s take a simple scenario where the livedata of datatype string is in ViewModel. Now, wherever the data-holder updated with new data, the UI should update.

让我们以一个简单的场景为例,其中数据类型string的实时数据位于ViewModel中。 现在,无论数据持有人使用新数据更新何处,UI都应该更新。

First, we need to create a ViewModel with a livedata of type string. Have a look:

首先,我们需要使用字符串类型的livedata创建一个ViewModel。 看一看:

class RendomViewModel : ViewModel() {


    // Create a LiveData with a String
    val status: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }


    // Rest of the ViewModel...
}

The next step is to observe the livedata from an Activity. Have a look:

下一步是观察活动中的实时数据。 看一看:

class NameActivity : AppCompatActivity() {


    // Use the 'by viewModels()' Kotlin property delegate
    private val model: NameViewModel by viewModels()


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)


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


        // Observe the LiveData
        model.status.observe(this, statusObserver)
    }
}

First, we created a string datatype observer and updated the UI inside it. Then it was assigned to the livedata in ViewModel with activity context. So livedata push updates to this observer only when the context that was supplied is active.

首先,我们创建了一个字符串数据类型观察器,并更新了其中的UI。 然后将其分配给具有活动上下文的ViewModel中的实时数据。 因此,仅当提供的上下文处于活动状态时,实时数据推送才会更新给该观察者。

什么是Kotlin Flow? (What is Kotlin Flow?)

Before Coroutines, most of the developers used Rxjava for asynchronous programming. When Kotlin came up with coroutines developers loved it — it solved all the conventional problems with async programming in more sophisticated way than Rxjava.

在发布协程之前,大多数开发人员都使用Rxjava进行异步编程。 当Kotlin提出协程时,开发人员就很喜欢它–它以比Rxjava更复杂的方式解决了异步编程中的所有常规问题。

Later on, coroutines came up with Flow API. Flow API in Kotlin is a better way to handle the stream of data asynchronously that executes sequentially. With Flow, coroutines turn out to be an alternative for Rxjava in Kotlin projects.

后来,协程提出了Flow API。 Kotlin中的Flow API是一种更好的异步处理顺序执行的数据流的方法。 有了Flow,协程在Kotlin项目中变成了Rxjava的替代品。

如何使用Kotlin Flow? (How to use Kotlin Flow?)

To keep things simple, let’s start with an example where we emit a list of values sequentially from the ViewModel and print them on a textview in the activity.

为简单起见,让我们从一个示例开始,在该示例中,我们依次从ViewModel发出值列表,并将它们打印在活动的textview上。

First, in the ViewModel, we need to create Flow and emit the values. Have a look:

首先,在ViewModel中,我们需要创建Flow并发出值。 看一看:

class RendomViewModel : ViewModel() {


    fun foo(): Flow<Int> = flow { 
       for (i in 1..5) {
           delay(100)
           emit(i)
       }
    }


    // Rest of the ViewModel...
}

In the ViewModel, we’ve created a function which returns a flow. It emits numbers 1 to 5 with a delay of 500 milliseconds on each iteration. In the real-time scenario the delay function replaced with complex async operations such as service calls or reading a large file. Now it’s time to update the UI using Flow in the activity.

在ViewModel中,我们创建了一个返回流的函数。 每次迭代都会发出1到5的数字,延迟为500毫秒。 在实时方案中,延迟功能已被复杂的异步操作(如服务调用或读取大文件)取代。 现在是时候使用Activity中的Flow更新UI了。

class NameActivity : AppCompatActivity() {


    // Use the 'by viewModels()' Kotlin property delegate
    private val model: NameViewModel by viewModels()


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)


       model.foo().collect { value -> tv_ouput.text = value }
    }
}

The Flow starts executing only when collect is invoked, as shown above.

流仅在调用collect时才开始执行,如上所述。

LiveData和Kotlin Flow之间的主要区别 (Key Difference between LiveData & Kotlin Flow)

Livedata is used to observe data without having any hazel to handle lifecycle problems. Whereas Kotlin flow is used for continuous data integration and it also simplified the asynchronous programming.

Livedata用于观察数据,而无需处理生命周期问题。 而Kotlin流用于连续数据集成,并且还简化了异步编程。

Take Room Library as an example. First, it used livedata to transmit data from the database to UI. It solved most of the existing problems. But when there are any future changes in the database livedata is helpless in this situation.

以“房间图书馆”为例。 首先,它使用livedata将数据从数据库传输到UI。 它解决了大多数现有问题。 但是,当数据库中将来有任何更改时,在这种情况下,实时数据将变得无能为力。

After a while, the room used Kotlin flow to solve this problem. With Flow as return-type, room created a new possibility of seamless data integration across the app between database and UI without writing any extra code.

一段时间后,房间使用Kotlin流解决了这个问题。 使用Flow作为返回类型,room创造了在数据库和UI之间跨应用程序进行无缝数据集成而无需编写任何额外代码的新可能性。

LiveData和Kotlin Flow的实时示例 (A Real-time example with LiveData & Kotlin Flow)

Let’s consider a real-time usecase where we show one minute timer after user requested for otp. There is timer for a minute in ViewModel. Every second, we need to update the UI. We will implement this feature using both livedata and Kotlin flow.

让我们考虑一个实时用例,其中在用户请求otp之后显示一个分钟计时器。 ViewModel中有一分钟的计时器。 每秒钟,我们需要更新UI。 我们将使用livedata和Kotlin流来实现此功能。

实时数据 (LiveData)

First, in the ViewModel, we create a timer with 60000 milliseconds(60 seconds) and 1000 milliseconds(one second) as an interval so that we can post updated time to livedata and refresh the UI. Have a look:

首先,在ViewModel中,我们创建一个计时器,其间隔为60000毫秒(60秒)和1000毫秒(一秒),以便我们可以将更新的时间发布到livedata并刷新UI。 看一看:

val timerUpdate : MutableLiveData<String> by lazy {
    MutableLiveData<String>()
}
var countDownTimer = object : CountDownTimer(60000,1000){
    override fun onFinish() {
        timerUpdate.value = "Resend OTP"
    }
    override fun onTick(millisUntilFinished: Long) {
        timerUpdate.value = "${millisUntilFinished/1000}"
    }
}

On the other hand, we observe this live-data in the activity to update the UI, as shown below:

另一方面,我们在活动中观察此实时数据以更新UI,如下所示:

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


viewmodel.timerUpdate.observe(this,timerObserver)

Kotlin流 (Kotlin Flow)

It is the same process even with Kotlin flow. Like posting and observing. But there will be some syntactical changes. First, let’s see how to use flow to create timer functionality in the view-model. Have a look:

即使使用Kotlin flow,也是如此。 喜欢发布和观察。 但是会有一些语法上的变化。 首先,让我们看看如何使用流在视图模型中创建计时器功能。 看一看:

val flowTimer : Flow<String> = flow {
    for (i in 1..60){
        emit(""+i)
        delay(1000)
    }
    emit("Resend OTP")
}

Now it’s time to collect the flow from activity to update UI. Have a look:

现在是时候收集来自活动的流程以更新UI。 看一看:

viewModel?.coroutineScope?.launch(Dispatchers.Main) {
    viewModel?.flowTimer?.collect{
        tv_resend?.text = it
    }
}

As we’re updating the UI, I’ve used coroutine scope with Dispatchers.Main. Inside the scope started collecting updates from Flow and updated UI.

在更新UI时,我已在Dispatchers.Main中使用了协程范围。 在示波器内部,开始从Flow和更新的UI收集更新。

结论 (Conclusion)

We’ve implemented timer using both livedata and Kotlin Flow. But when it comes to the question: which one to use? It is more dependent on the core functionality of the feature. Like in the case of timer — it’s a continuous data flow between ViewModel and UI, so I prefer to use Kotlin flow.

我们已经使用livedata和Kotlin Flow实现了计时器。 但是当涉及到一个问题时:使用哪个? 它更多地取决于功能的核心功能。 就像使用计时器一样,它是ViewModel和UI之间的连续数据流,因此我更喜欢使用Kotlin流。

Kotlin flow primarily focuses on seamless data integration, so it makes sense. So when you’re dealing with constant data flow which might include complex async operations try to do it with Kotlin flow and use livedata for other things like service calls, state changes and stuff like that.

Kotlin流主要专注于无缝数据集成,因此很有意义。 因此,当您处理可能包含复杂异步操作的恒定数据流时,请尝试使用Kotlin流进行处理,并将livedata用于服务调用,状态更改之类的其他事情。

I hope you learn something useful, thanks for reading.

希望您能学到一些有用的东西,感谢您的阅读。

翻译自: https://medium.com/android-dev-hacks/exploring-livedata-and-kotlin-flow-7c8d8e706324

livedata

 类似资料: