You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose和Dagger-Hilt中ViewModel使用ActivityResultRegistry的正确方案

在Jetpack Compose + Dagger-Hilt中实现蓝牙可发现性的问题

背景

我正在使用Jetpack Compose和Dagger-Hilt开发一款具备蓝牙功能的应用,核心需求之一是在应用内开启设备可发现性。这类调用系统Activity(比如请求蓝牙可发现性、选择照片、打开设置)的场景,常规流程是将ActivityResultLauncher注册到ActivityResultRegistry后再启动,但我发现相关讨论资料极少。

我的项目仅使用单个ComponentActivity、无Fragment,且遵循UI与逻辑分离的原则,自然希望将开启可发现性的逻辑放在ViewModel中处理,但相关资料十分匮乏——即便使用Fragment,这类逻辑也应该借助ViewModel实现。

现有测试实现(可运行但存稳定性疑虑)

我编写了一段测试代码,点击按钮调用becomeDiscoverable()后,Android 8会弹出原生对话框请求开启可发现性,Android 10无对话框但功能正常,但我不确定这段代码的稳定性:

class MainViewModel @AssistedInject constructor(
    private val context: Application,
    @Assisted private val registry: ActivityResultRegistry,
) : ViewModel() {

    var enableDiscoverableLauncher: ActivityResultLauncher<Intent>? = null
        private set

    fun becomeDiscoverable(duration: Int = 20) {
        enableDiscoverableLauncher = registry.register(
            "DISCOVERABLE_ENABLER", ActivityResultContracts.StartActivityForResult()
        ) { }
        val discoverableIntent: Intent =
            Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply {
                putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, duration)
            }
        enableDiscoverableLauncher?.launch(discoverableIntent, ActivityOptionsCompat.makeBasic())
    }

    //@AssistedFactory is below...
}

现有疑虑

ViewModel的生命周期长于Activity,我担心配置变更时,作为ActivityResultRegistryOwner的ComponentActivity重建后,此时调用becomeDiscoverable()会导致崩溃——虽然目前未复现该问题,但存在理论风险。不过实际测试中,Activity重建后ViewModel中activityResultRegistry的引用仍有效,becomeDiscoverable()仍能成功调用。

对参考方案的困惑

根据某Stack Overflow问题的Accepted Answer,我可以在Compose组合中获取并记住LocalActivityResultRegistryOwner.current!!.activityResultRegistry,再通过Dagger-Hilt的辅助注入获取持有该引用的ViewModel。但答案中的这段内容让我困惑:

I am assuming that you are using Compose inside a ComponentActivity anyway, so you will never receive a null reference when accessing ActivityResultRegistryOwner.current, so if you do not want to deal with a nullable type, you can use the !! operator.

我有两点疑问:

  • 为什么仅在ComponentActivity中,LocalActivityResultRegistryOwner.current不会为null?
  • 该问题的提问者为何不使用ViewModel来处理相关逻辑?

核心问题

在Jetpack Compose中,如何正确实现与Activity所属的Android原生对象(如ActivityResultRegistry)的交互?


内容的提问来源于stack exchange,提问作者Tim Korelov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 11:36:03