kotlin库

    科技2022-08-03  106

    kotlin库

    什么是LiveData? (What Is LiveData?)

    We can describe LiveData as an observable data holder class, meaning it can hold a set of data that can be observed from other Android UI components such as activities, fragments, and services.

    我们可以将LiveData描述为可观察的数据持有者类,这意味着它可以保存可以从其他Android UI组件(例如活动,片段和服务)观察到的一组数据。

    LiveData is lifecycle-aware. Once the component that is observing data is destroyed or not active, LiveData stops publishing data to that observer. This solves many common problems for Android developers.

    LiveData具有生命周期意识。 一旦用于观察数据的组件被破坏或不活动,LiveData将停止将数据发布到该观察器。 这为Android开发人员解决了许多常见问题。

    Most developers use LiveData in an MVVM architecture to communicate or transmit data from the ViewModel to the view. This ensures lifecycle-aware communication between them by reducing memory leaks.

    大多数开发人员在MVVM架构中使用LiveData来将数据从ViewModel传递或传输到视图。 这样可以通过减少内存泄漏来确保它们之间的生命周期感知通信。

    But there are cases where I saw developers use LiveData to communicate between a repository and a ViewModel, including a Google I/O application. Using LiveData in this case seems correct. After all, it’s designed to hold and pass the data. But it’s not recommended, and you’ll learn why in the following sections.

    但是在某些情况下,我看到开发人员使用LiveData在存储库和ViewModel(包括Google I / O应用程序)之间进行通信。 在这种情况下使用LiveData似乎是正确的。 毕竟,它是设计用来保存和传递数据的。 但不建议这样做,您将在以下各节中了解原因。

    使用LiveData的优势: (Advantages of using LiveData:)

    No memory leaks

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

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

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

    资源共享

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

    Before coroutines, most developers used RxJava for asynchronous programming. When Kotlin came up with coroutines, developers loved them. They solved all the traditional problems with async programming in a more sophisticated way than RxJava.

    在进行协程之前,大多数开发人员都使用RxJava进行异步编程。 当Kotlin提出协程时,开发人员很喜欢它们。 他们使用异步编程以比RxJava更复杂的方式解决了所有传统问题。

    Before coroutines, we had to call an asynchronous function like a service call, retrieving data from the database, reading files, or anything via callback. We could only resume the actual work when we knew that the operation was finished, like mobiles updating the UI after receiving data from your servers.

    在进行协程之前,我们必须调用异步函数(如服务调用),从数据库中检索数据,读取文件或通过回调进行任何操作。 我们只有在知道操作已完成时才能恢复实际工作,例如移动设备在从您的服务器接收数据后更新UI。

    Coroutines offer a solution to this through suspend functions. Suspend functions can suspend the execution of the current thread until the job is completed. Have a look:

    协程通过suspend功能为此提供了解决方案。 Suspend功能可以挂起当前线程的执行,直到作业完成。 看一看:

    suspend fun getFilteredItems(token : String){ listItems = getItems(token) filteredItems = getFilteredItems(listItems) update() } suspend fun getItems( ... ) suspend fun getFilteredItems( ... ) fun update()

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

    后来,协程提出了Flow API。 这是一种更好的异步处理顺序执行的数据流的方法。 使用Flow,协程在Kotlin项目中被证明是RxJava的替代品。

    With the ability to sequentially execute complex operations and continuous data flow, Kotlin’s Flow API is more powerful.

    Kotlin的Flow API具有顺序执行复杂操作和连续数据流的功能,功能更强大。

    为什么要在存储库中使用Kotlin Flow? (Why Should We Use Kotlin Flow in Repositories?)

    This is an interesting question.

    这是个有趣的问题。

    Let me first answer a different one.

    首先让我回答一个不同的问题。

    为什么不使用LiveData? (Why not LiveData?)

    The core purpose of LiveData is to hold a set of data that can be observed. What makes it stand out from other observables is that it’s lifecycle-aware. One of the key things is that LiveData observers are always called on the main thread.

    LiveData的核心目的是保存一组可以观察到的数据。 使它在其他可观察对象中脱颖而出的原因是它具有生命周期意识。 关键之一是始终在主线程上调用LiveData观察器。

    Whereas we use LiveData in the repository to pass the data to the ViewModel, here the ViewModel should act as an observer, so we need to invoke the main thread’s execution. ViewModels are not recommended to use main thread operations.

    尽管我们在存储库中使用LiveData将数据传递给ViewModel,但是在这里ViewModel应该充当观察者,因此我们需要调用主线程的执行。 不建议ViewModel使用主线程操作。

    In real-time, we often use transformations on the data that we obtained from the servers. By using LiveData, we have to do it in the main thread, which is again not recommended.

    实时地,我们经常对从服务器获得的数据进行转换。 通过使用LiveData,我们必须在主线程中执行此操作,同样不建议这样做。

    When you see the core purpose of LiveData, it makes sense that the observers are always called on the main thread because it’s often used to update the UI thread.

    当您看到LiveData的核心目的时,便总是在主线程上调用观察者,因为它通常用于更新UI线程,这是有道理的。

    It’s not the first time LiveData has been misused. Before Kotlin Flow, developers requested the Android team to make it something like RxJava. Instead, they created coroutines and explained that LiveData is a simple data holder.

    这不是第一次滥用LiveData。 在Kotlin Flow之前,开发人员要求Android团队使用RxJava之类的工具。 相反,他们创建了协程并解释说LiveData是一个简单的数据持有者。

    为什么选择Kotlin Flow? (Why Kotlin Flow?)

    Coroutines are designed to execute complex asynchronous operations cleanly and sequentially. Coroutines suspending functions asynchronously returns a single value, but how can we return multiple asynchronously computed values? This is where Kotlin Flows shines.

    协程被设计为清晰,顺序地执行复杂的异步操作。 协程挂起函数异步返回一个值,但是如何返回多个异步计算的值呢? 这就是Kotlin Flows闪耀的地方。

    Flow is explicitly designed to handle complex asynchronous operations effectively and emit multiple times as per the requirement. Unlike channels, flows are cold streams just like sequences. The code inside a flow builder does not run until the Flow is collected.

    Flow被明确设计为有效处理复杂的异步操作,并根据要求发出多次。 与通道不同,流量像序列一样是冷流 。 在收集流之前,流构建器中的代码不会运行。

    So these abilities make Kotlin Flow an excellent alternative to LiveData in repositories. Flow offers similar functionality: builders, cold streams, and useful helpers (e.g. transforming data). Unlike LiveData, they are not bound to the lifecycle and provide more control over the execution context.

    因此,这些功能使Kotlin Flow成为存储库中LiveData的绝佳替代品。 Flow提供了类似的功能:构建器,冷流和有用的帮助器(例如,转换数据)。 与LiveData不同,它们不受生命周期的束缚,并提供对执行上下文的更多控制。

    用Kotlin Flow替换LiveData (Replace LiveData With Kotlin Flow)

    Now that we know why we need to use Kotlin Flow in repositories instead of LiveData, it’s time to learn how to do it. First, let’s see a blueprint of an existing project:

    现在,我们知道了为什么需要在存储库中使用Kotlin Flow而不是LiveData,是时候学习如何使用它了。 首先,让我们看一下现有项目的蓝图:

    Photo by the author. 图片由作者提供。

    Our goal here is to replace the LiveData between the ViewModel and repository with Kotlin Flow. To do so, first we need to replace the output of the repository function with Kotlin Flow, as shown below:

    我们的目标是用Kotlin Flow替换ViewModel和存储库之间的LiveData。 为此,首先我们需要用Kotlin Flow替换存储库函数的输出,如下所示:

    suspend fun getCategories(offset : Int, limit : Int, country : String ): Flow<CustomResult<AlbumsResponse>> return flow { try { emit(CustomResult.Loading(true)) val url = "$baseUrl$endpointAlbums?country=$country&limit=$limit&offset=$offset" val response = client.request<AlbumsResponse>(url) { method = HttpMethod.Get headers { append("Accept", "application/json") append("Authorization", "Bearer $authKey") } } emit(CustomResult.Success(response)) }catch (e : Exception){ emit(CustomResult.Error.RecoverableError(e)) } }.flowOn(Dispatchers.IO) }

    Here, we need to replace LiveData with Flow in the return type. As you see the execution, Flow first emits the loading state. Then, after the completion of the Ktor service request, Flow again emits the response. If there is an exception, we can emit it in the catch block.

    在这里,我们需要用返回类型中的Flow替换LiveData。 如您所见,Flow首先发出加载状态。 然后,在完成Ktor服务请求后,Flow再次发出响应。 如果有异常,我们可以在catch块中发出它。

    Remember, when I said we have more control over the execution using Flow, by using flowOn, we can explicitly change the execution thread as per the requirement. It’s one of many handy functions such as debounce, delayFlow, and more.

    记住,当我说我们有过使用流执行更多的控制权,通过使用flowOn ,我们可以明确地改变执行线程按要求。 这是许多方便的功能,如一个debounce , delayFlow ,等等。

    Now that we have successfully implemented Flow in the repository, let’s see how to observe that data in the ViewModel. Have a look:

    现在,我们已经在存储库中成功实现了Flow,让我们看看如何在ViewModel中观察该数据。 看一看:

    @UseExperimental(FlowPreview::class) fun getCategories(){ viewModelScope.launch { spotifyRepo.getCategories(offset = presentOffset, country = country, limit = limitResultsPerPage ).collect { liveDataCategoriesList.postValue(it) } } }

    Here, we use the viewmodelscope to restrict the request’s scope and then invoke the collect function on the Flow to trigger the request. Inside the collect receiver, we can post the data via LiveData to update the UI. Now the blueprint of the existing project is as shown below:

    在这里,我们使用viewmodelscope限制请求的范围,然后在Flow上调用collect函数以触发请求。 在collect接收器内部,我们可以通过LiveData发布数据以更新UI。 现在,现有项目的蓝图如下所示:

    Photo by the author. 图片由作者提供。

    In the ViewModel, we can use the map function on the Kotlin Flow to implement mapping. This comes in handy when we have two different models for the server response and local usage. Have a look:

    在ViewModel中,我们可以使用Kotlin Flow上的map函数来实现映射。 当我们有两种不同的服务器响应和本地使用模型时,这很方便。 看一看:

    fun getCategories(){ viewModelScope.launch { spotifyRepo.getCategories(offset = presentOffset, country = country, limit = limitResultsPerPage ).map { // implement mappers }.collect { liveDataCategoriesList.postValue(it) } } }

    结论 (Conclusion)

    That is all for now. I hope you learned something useful. Thanks for reading.

    到此为止。 我希望你学到了一些有用的东西。 谢谢阅读。

    翻译自: https://medium.com/better-programming/no-more-livedata-in-repositories-in-kotlin-85f5a234a8fe

    kotlin库

    相关资源:kubernetes官方文档中文版
    Processed: 0.010, SQL: 8