当前位置: 首页 > 知识库问答 >
问题:

LifecycleScope.LaunchWhenStarted安全吗?如果不安全,为了什么情况?

王成化
2023-03-14

在我的应用程序中,我使用coroutine和flow向API发送请求。当请求出现时,我更改了stateFlow的值,以便我的activity中的收集器看到并执行其工作。这是一个简单的场景。在android网站(https://developer.android.com/kotlin/flow/stateflow-and-sharedflow)中,建议了2种方法。在这种情况下,我应该倾向于哪种方法?

以下是上述链接的引文。:

使用launchWhen()函数收集Stateflow是安全的,因为它们的作用域是ViewModel,使它们在视图转到后台时保留在内存中,并且它们只通过通知视图有关UI状态来完成轻量级工作。然而,问题可能会出现在其他做更密集工作的生产者身上。

在这段引文中,说第一种方法是安全的,但在最后一句中有一个警告。那警告是为了什么?我不明白它是否安全。生产者是否继续采用第一种方法?在我的情况下,如果请求还没有来,而用户在后台运行应用程序,制作者是否工作并尝试更新UI?

第一种方法:

class LatestNewsActivity : AppCompatActivity() {
    private val latestNewsViewModel = // getViewModel()

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        // This coroutine will run the given block when the lifecycle
        // is at least in the Started state and will suspend when
        // the view moves to the Stopped state
        lifecycleScope.launchWhenStarted {
            // Triggers the flow and starts listening for values
            latestNewsViewModel.uiState.collect { uiState ->
                // New value received
                when (uiState) {
                    is LatestNewsUiState.Success -> showFavoriteNews(uiState.news)
                    is LatestNewsUiState.Error -> showError(uiState.exception)
                }
            }
        }
    }
}

第二种方法:

class LatestNewsActivity : AppCompatActivity() {
    ...
    // Coroutine listening for UI states
    private var uiStateJob: Job? = null

    override fun onStart() {
        super.onStart()
        // Start collecting when the View is visible
        uiStateJob = lifecycleScope.launch {
            latestNewsViewModel.uiState.collect { uiState -> ... }
        }
    }

    override fun onStop() {
        // Stop collecting when the View goes to the background
        uiStateJob?.cancel()
        super.onStop()
    }
}

在这种非常简单的情况下,哪种方法更合适?

共有1个答案

杜砚
2023-03-14

无论如何,如果视图处于停止状态或低于启动状态,则collection块将不工作。

但是对于流有一个叫做订阅计数的东西,它指示有多少订阅者希望收集该流。诀窍来了。当视图移动到小于STARTED状态的状态时,Collection块将挂起,但流的订阅计数保持不变,这将流生成器保留在内存中。但是如果您采用第二种方法取消作业,则在取消作业时订阅计数将减少,并且会防止流生成器留在内存中,这在不需要时会浪费资源。

现在,他们在最后一句话中给出的警告是针对stateflow以外的其他流生产者的。例如,flow builder函数flow{//Some Consensive work}。StateFlow的工作方式不同,因为它只是向activity/片段发出UI状态,而不包含任何代码块(昂贵的代码)。因此使用launchWhen函数收集StateFlow是安全的。

这是在UI状态发射的情况下所希望的工作,因为您需要流发射更改,即使片段在backstack中且不活动,但当它从backstack中再次还原时,也应该获得最新的更改。在这里,StateFlow应该保留在范围为ViewModel的内存中。

 类似资料:
  • 黑客有没有办法抓住这个按钮并“点击”它? 是否需要添加另一层安全性?

  • 我正在考虑使我的应用程序更安全,并了解正在发生的一切。 我在Spring Boot有一个登录名。该登录调用UserDetailsService实现,如下所示: 这为我创建了一个具有用户角色的会话,以便我可以配置网络安全配置器适配器等。 所以我的问题是,用JWT添加过滤器到底做了什么?SpringSecurity在默认情况下是否已经这样做了,因为我所做的已经创建了一个经过授权和身份验证的用户。 谢了

  • 问题内容: 我是JDBC的新手,新项目要求我使用JDBC。我想知道的是 JDBC安全吗? 如何防止类似“ Mysql Injection”的问题? 使用JDBC时需要注意哪些安全问题? 以及如何确保优化安全性,以防止黑客入侵数据库? 编辑: 我尝试过google,如果我使用google: “ php mysql安全问题” =>它给出了很多结果 如果我谷歌: “ jdbc mysql安全问题” =>

  • 本文向大家介绍Java 安全模型,你了解了吗,包括了Java 安全模型,你了解了吗的使用技巧和注意事项,需要的朋友参考一下 前言 作为一种诞生于互联网兴起时代的语言,Java 从一开始就带有安全上的考虑,如何保证通过互联网下载到本地的 Java 程序是安全的,如何对 Java 程序访问本地资源权限进行有限授权,这些安全角度的考虑一开始就影响到 Java 语言的设计与实现。可以说 Java 在这些方

  • 根据http://projects.spring.io/spring-security-oauth/docs/oauth2.html: 请注意。应该使用Spring Security保护授权endpoint/OAUTH/Authorize(或其映射的替代),以便仅对经过身份验证的用户进行访问。 这是为什么?一个endpoint需要一个授权授予来交换一个授权代码,这听起来是不对的。这就像登录页面的登