使用更为安全的方式收集 Android UI 数据流

本文探讨了在Android应用中如何安全收集Kotlin数据流,以避免资源浪费和后台泄漏。推荐使用LifecycleOwner.addRepeatingJob、Lifecycle.repeatOnLifecycle和Flow.flowWithLifecycle API,这些API能在UI不可见时自动停止数据流收集,从而提高效率和安全性。对比LiveData,Flow提供了更灵活的选项和更丰富的操作符。此外,文章还提到了在Jetpack Compose中安全收集数据流的方法。
摘要由CSDN通过智能技术生成

在 Android 应用中,通常需要从 UI 层收集 Kotlin 数据流,以便在屏幕上显示数据更新。同时,您也会希望通过收集这些数据流,来避免产生不必要的操作和资源浪费 (包括 CPU 和内存),以及防止在 View 进入后台时泄露数据。

本文将会带您学习如何使用 LifecycleOwner.addRepeatingJob、Lifecycle.repeatOnLifecycle 以及 Flow.flowWithLifecycle API 来避免资源的浪费;同时也会介绍为什么这些 API 适合作为在 UI 层收集数据流时的默认选择。

资源浪费

无论数据流生产者的具体实现如何,我们都推荐从应用的较底层级暴露 Flow API。不过,您也应该保证数据流收集操作的安全性。

使用一些现存 API (如 CoroutineScope.launch、Flow.launchIn 或 LifecycleCoroutineScope.launchWhenX) 收集基于 channel 或使用带有缓冲的操作符 (如 buffer、conflate、flowOn 或 shareIn) 的冷流的数据是不安全的,除非您在 Activity 进入后台时手动取消启动了协程的 Job。这些 API 会在内部生产者在后台发送项目到缓冲区时保持它们的活跃状态,而这样一来就浪费了资源。

注意:冷流是一种数据流类型,这种数据流会在新的订阅者收集数据时,按需执行生产者的代码块。

例如下面的例子中,使用 callbackFlow 发送位置更新的数据流:

// 基于 Channel 实现的冷流,可以发送位置的更新
fun FusedLocationProviderClient.locationFlow() = callbackFlow<Location> {
    val callback = object : LocationCallback() {
        override fun onLocationResult(result: LocationResult?) {
            result ?: return
            try { offer(result.lastLocation) } catch(e: Exception) {}
        }
    }
    requestLocationUpdates(createLocationRequest(), callback, Looper.getMainLooper())
        .addOnFailureListener { e ->
            close(e) // 在出现异常时关闭 Flow
        }
    // 在 Flow 收集结束时进行清理操作 
    awaitClose {
        removeLocationUpdates(callback)
    }
}

注意:callbackFlow 内部使用 channel 实现,其概念与阻塞队列十分类似,并且默认容量为 64。

使用任意前述 API 从 UI 层收集此数据流都会导致其持续发送位置信息,即使视图不再展示数据也不会停止!示例如下:

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

        // 最早在 View  处于 STARTED 状态时从数据流收集数据,并在
        // 生命周期进入 STOPPED 状态时 SUSPENDS(挂起)收集操作。
        // 在 View 转为 DESTROYED 状态时取消数据流的收集操作。
        lifecycleScope.launchWhenStarted {
            locationProvider.locationFlow().collect {
                // 新的位置!更新地
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值