jetpack使用
Jetpack Compose is coming on leaps and bounds and we’ve had a glimpse of what LiveData usage within compose may look like but nothing officially recommended as the “go to” standard.
Jetpack Compose突飞猛进,我们瞥见了Compose中LiveData的使用情况,但官方没有正式建议将其作为“执行”标准。
Jetpack Compose provides a very convenient way of hooking into the compose lifecycle with a few callbacks the first of which is onActive { }
.
Jetpack Compose提供了一种非常方便的方法,可以通过几个回调(其中第一个是onActive { }
回调到组合生命周期。
合成生命周期回调 (Composition lifecycle callbacks)
In our compose functions (those marked with @Composable
we can hook into this composition quite simply by doing the following.
在我们的compose函数(标有@Composable
函数)中,我们可以通过执行以下操作非常简单地挂接到此组合中。
In the example our root composition starts with setContent
(if you are not familiar with compose yet, this is where we can write our declarative UI). Inside this block, we can put our onActive
composition lifecycle callback to add a block of code that will be only executed once per composition. Within the onActive
block we can specify another block onDispose
which will get called when this composition is invalidated, therefore providing convenient hooks for callback/subscription based API’s such as LiveData
.
在该示例中,我们的根组合以setContent
开始(如果您还不熟悉compose,则可以在此处编写声明性UI)。 在此代码块中,我们可以将onActive
合成生命周期回调添加到代码块中,每个合成代码仅执行一次。 在onActive
块中,我们可以指定另一个onDispose
块,当此组合无效时将调用该块,因此为基于回调/订阅的API(如LiveData
提供了方便的钩子。
LiveData集成示例 (LiveData integration example)
Given the basics out of the way the next code snippet shows a usage pattern of a custom function observe
that makes use of compose lifecycle callbacks which accepts a LiveData as its first argument and has a convenient callback onResult
where the live data result will be delivered (effectively wrapping the observe behaviour of live data).
由于基本的方式进行下面的代码片段显示了一个自定义函数的使用模式observe
,使得使用的撰写生命周期回调,它接受一个LiveData作为第一个参数,并有一个方便的回调onResult
在实时数据结果将交付(有效地包装实时数据的观察行为)。
The example is not small, but requires some explanation. First up we remember
a model HelloModel
. This model is annotated with @Model
which is composes way of specifying observable data that when changed, can cause a recomposition.
这个例子并不小,但是需要一些解释。 首先,我们remember
一个模型HelloModel
。 该模型带有@Model
注释,该模型构成了指定可观察数据的方式,这些数据在更改时会导致重新组合。
Next up on our observe
block which we give the result of a function call to getHello
that returns a LiveData
. (the implementation of the observe
function is where the magic happens which I will show and break down later).
接下来,在我们的observe
块中,我们给出对getHello
的函数调用的结果,该函数返回LiveData
。 ( observe
功能的实现是发生魔术的地方,我将在后面进行演示并分解)。
As mentioned we specify another block inside the observe
call onResult { }
. Here we can take the result of the live data call and pass it to a property on our model with hello.state = result
, where result is a property available in only the onResult
block.
如前所述,我们在observe
调用onResult { }
指定了另一个块。 在这里,我们可以获取实时数据调用的结果,并使用hello.state = result
将其传递给我们模型的属性,其中result是仅在onResult
块中可用的属性。
The final code block in setContent
is where we decide which message to show depending on the value ofHelloModel::state
. It is a simple when(state){}
block when that will show an appropriate message depending on the state being Pending
, Hello
or Error
. (Currently no error could occur with this code example, however for brevity its here to give you an idea of how you could handle an error).
setContent
的最后一个代码块是我们根据HelloModel::state
的值决定显示哪个消息的HelloModel::state
。 这是一个简单的when(state){}
块,何时显示取决于状态Pending
, Hello
或Error
的适当消息。 (当前此代码示例不会发生任何错误,但是为了简洁起见,在这里可以使您了解如何处理错误)。
observe
功能的observe
(Under the hood of the observe
function)
Inside this custom observe
function is where all the magic happens. Where we hook into the composition using onActive
and onDispose
.
在此自定义的observe
功能内,发生了所有魔术。 我们使用onActive
和onDispose
钩住合成的onDispose
。
The function is not as simple as it could be since I plan to expand it if nothing more comes along hence the usage of receivers for scoped functionality.
该功能并非如此简单,因为我打算在没有其他功能的情况下对其进行扩展,因此将接收器用于范围内的功能。
So what is going on here? Firstly the observe
function takes an argument data: LiveData
which is the live data we wish to load. secondly we have a trailing lambda block: ObserveScope
. which is effectively is a delegate for our live data observer (which we never need to use with this setup).
那么这是怎么回事? 首先, observe
函数接受一个参数data: LiveData
,这是我们希望加载的实时数据。 其次,我们有一个尾随lambda block: ObserveScope
。 这实际上是我们的实时数据观察者的委托(在此设置中我们永远不需要使用)。
The function does some setup and calls context.onStartBlock()
giving integrations the chance to hook into the moment just before the LiveData is observed with onStart {}
(maybe for showing a loading spinner or something).
该函数进行一些设置并调用context.onStartBlock()
从而使集成有机会挂在使用onStart {}
观察LiveData之前的那一刻(可能用于显示加载微调框或其他内容)。
Moving on we create an observer
and in the onChanged
callback we call context.onResultBlock
which ultimately calls onResult {}
which we saw previously in the usage sample.
继续,我们创建一个observer
,在onChanged
回调中,我们调用context.onResultBlock
,最终调用在用法示例中先前看到的onResult {}
。
Next we observeForever(observer)
which kicks off the live data observation. finally we declare a onDispose
block and ensure we remove observers. The rest of the code is mostly specific to my exploration and usage of this pattern.
接下来,我们observeForever(observer)
的实时数据。 最后,我们声明一个onDispose
块并确保我们删除观察者。 其余的代码大部分是我对这种模式的探索和使用。
Looking back at the observe
function you may have noticed that the data: LiveData
argument is annotated with @Pivotal
. What this does is tell the compose compiler that this argument should act as unique ID for this block and if a recomposition occurs and this unique ID changes then this part becomes invalid and should be recomposed causing the onDispose
block to be called and onActive
to be called again. Without compose knowing its unique this would never happen.
回顾一下observe
函数,您可能已经注意到data: LiveData
参数用@Pivotal
注释。 这样做是告诉Compose编译器该参数应作为此块的唯一ID,并且如果发生重组且此唯一ID发生更改,则此部分将变为无效,并应进行重组,从而导致调用onDispose
块和onActive
被调用再次。 如果不知道它的独特性,这将永远不会发生。
处理错误并重试 (Handling errors and retry)
So I mentioned that error handling is not in the usage example snippet (well handling is there just not throwing an error and retrying), so the only way I have found out so far to retry a composition is by using a convenient composable called Recompose
which I will explain with another example that builds on the previous example.
因此,我提到了使用示例代码段中没有错误处理(很好的处理只是不引发错误并重试),所以到目前为止,我发现重试合成的唯一方法是使用一个方便的可组合项,称为Recompose
我将用另一个基于先前示例的示例进行解释。
Here we wrap our code with aRecompose
block which gives us a lambda callback we call recompose
which we call later if an error occurs as the action of a button click. The code mimics an error with a field doError
firstly set to true which causes loading with an error. Then in our retry Button
onClick
callback we set doError
to false so when we call recompose()
Our live data will be loaded again but this time with a successful result HelloResult.Hello
.
在这里,我们用Recompose
块包装代码,该块为我们提供了一个lambda回调(称为recompose
,如果在单击按钮时发生错误,我们将在稍后调用。 该代码模仿了一个错误,该错误将首先将doError
字段设置为true,从而导致加载错误。 然后,在重试Button
onClick
回调中,将doError
设置为false,这样,当我们调用recompose()
将再次加载实时数据,但这一次成功的结果是HelloResult.Hello
。
An important point to note is we check hello.state != result
before setting the state on the model as I found it causes infinite recomposition.
需要注意的重要一点是,我们在模型上设置状态之前检查hello.state != result
,因为我发现它会导致无限重组。
I don’t know if this is the best way, to use Recompose in this manner, what do you think?
我不知道这是否是最好的方法,以这种方式使用Recompose,您如何看待?
结论 (Conclusion)
These are my most recent dabbling with Jetpack Compose and LiveData integration, not 100% sure if its right however that was partly the point of this article, to get my thoughts out there and what I have found out so far.
这些是我最近对Jetpack Compose和LiveData集成的研究,不确定100%是否正确,但这是本文的重点,以便使我的想法和到目前为止的发现。
I am using this method in my little compose app and it works well so far https://github.com/fluxtah/memset
我在我的小型撰写应用程序中使用了此方法,到目前为止效果很好https://github.com/fluxtah/memset
What do you think? Have you found a better way of LiveData integration that ticks all the boxes such as error handling and reloading (recomposing?) I am interested to hear about this in the comments or reach out to me, maybe join the Jetpack Compose slack channel and you can find me there! :)
你怎么看? 您是否找到了一种更好的LiveData集成方式,可以将所有框打勾,例如错误处理和重新加载(重新构建?)。我有兴趣在评论中听到此消息或与我联系,也许可以加入Jetpack Compose松弛频道,您可以在那找到我! :)
翻译自: https://medium.com/@fluxtah/another-way-of-using-livedata-with-jetpack-compose-77a28c287af9
jetpack使用