首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

从协程启动时,Activity会启动两次

是因为在Android中,协程是基于线程的非阻塞并发编程的一种方式。当我们在Activity中启动一个协程时,协程会在后台线程中执行,而Activity本身是在主线程中运行的。

因此,当协程启动时,会触发Activity的生命周期方法,包括onCreate()、onStart()、onResume()等。这是第一次启动Activity。然后,协程在后台线程中执行任务,当任务完成后,会通过主线程将结果返回给Activity。

由于协程的执行是异步的,当协程任务完成后,Activity可能已经处于不可见或已销毁的状态。当协程返回结果时,Activity可能已经重新创建或重新启动。这就导致了Activity会再次启动,这是第二次启动Activity。

为了解决这个问题,可以在Activity的onCreate()方法中添加判断,只有当Activity是第一次创建时才执行相关初始化操作,避免重复执行。可以使用一个标志位来记录Activity是否已经创建过。

另外,还可以使用ViewModel来保存数据和状态,以便在Activity重新创建时能够恢复之前的状态。

总结起来,从协程启动时,Activity会启动两次是因为协程是在后台线程中执行的异步任务,当任务完成后,Activity可能已经重新创建或重新启动,导致Activity会再次启动。为了解决这个问题,可以在Activity的生命周期方法中添加判断,只在第一次创建时执行相关操作,并使用ViewModel来保存数据和状态。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

理解、LiveData 和 Flow

编写的过程就和编写普通的代码块差不多,编译器则会帮助开发者完成异步化处理。 结构并发性。这个可以理解为针对操作的垃圾搜集器,当一个操作不再需要被执行时,自动取消它。...如何启动和取消协 在 Jetpack 组件里,我们为各个组件提供了对应的 scope,比如 ViewModel 就有与之对应的 viewModelScope,如果您想在这个作用域里启动,使用如下代码即可...lifecycleScope.launch { // Run } } } 复制代码 有些时候,您可能还需要在生命周期的某个状态 (启动时...而如果您的操作只是清理一下本地存储,那可以考虑使用 Application Scope,因为这个操作的重要性不是很高,完全可以等到下次应用启动时再做。...绝大部分情况下,的取消操作是自动的,毕竟我们在对应的作用域里启动一个时,也同时明确了它会在何时被取消。但我们有必要讲一讲如何在内部来手动取消协

2.2K20

Android面试题之Kotlin Jetpack组件LifecycleScope

例如,当一个 Activity 被销毁时,在 LifecycleScope 内启动自动取消。...如果生命周期 CREATED 状态降到 DESTROYED,会被取消。例如,在 Activity 或 Fragment 被销毁时,会被取消。...如果生命周期 CREATED 状态降到 DESTROYED,会被取消。例如,在 Activity 或 Fragment 被销毁时,会被取消。...launchWhenResumed: 在 Activity 的生命周期至少达到 RESUMED 状态时启动。...当 Activity 被销毁(例如屏幕旋转或用户离开),生命周期会先降到 STARTED(如果用户稍后返回该活动),继而完全销毁,这时自动取消,不会保留对 Activity 的引用,从而避免内存泄漏

14410
  • Kotlin实现原理:CoroutineScope&Job

    例如,在Android中使用来请求数据,当接口还没有请求完成时Activity就已经退出了,这时如果不停止正在运行的将会造成不可预期的后果。...所以在Activity中我们都推荐使用lifecycleScope来启动,lifecycleScope可以让具有与Activity一样的生命周期意识。...Activity销毁的时候终止的运行。...Job 基本上每启动一个就会产生对应的Job,例如 lifecycleScope.launch { } launch返回的就是一个Job,它可以用来管理,一个Job中可以关联多个子Job,同时它也提供了通过外部传入...项目 android_startup: https://github.com/idisfkj/android-startup 提供一种在应用启动时能够更加简单、高效的方式来初始化组件,优化启动速度。

    1.6K40

    Kotlin | 使用手册(不间断更新)

    作用域构建器 runBlocking 阻塞当前线程,直到结束。...,但是这样使用也不是我们所推荐的方式,特别是如果我们忘记了对新启动的引用,它还是继续运行。...它启动了一个单独的,这是一个轻量级的线程并与其它所有的一起并发的工作。...,将直接运行在当前线程 子 当一个被其他在 CoroutineScope 启动时,它将通过 CoroutineScope.CoroutineContext 来承袭上下文,并且这个新将成为父的子作业...当一个父被取消时,同时意味着所有的子取消。 然而,如果此时用 GlobalScope.launch启动,则它与父的作用域将无关并且独立运行。

    2.4K20

    Kotlin解析系列(上):调度与挂起

    使用线程更为便捷: 图片 这个Thread方法有个参数start默认为true,即创造出来的线程默认启动,你可以自定义启动时机: 图片 2.2 启动需要三部分:上下文、启动模式、体。...3.4 启动模式 前述进行创建启动时涉及到了启动模式CoroutineStart,其是一个枚举类,为构建器定义启动选项。在构建的start参数中使用。...其实cancel 调用一定会将该 job 的状态置为 cancelling,只不过ATOMIC 模式的启动时无视了这一状态。...“挂起”是指它当前线程脱离,切换到另一个线程运行。当线程运行到suspend函数时,暂时挂起这个函数及后续代码的执行。简而言之,挂起函数是一个可以启动、暂停和恢复的函数。...5.3 运行原理 前述相关示例更多是为了验证分析的一些特性,这里的创建、启动、恢复、线程调度,切换等详细解析的实现。

    1.9K40

    解决Android开发中的痛点问题用Kotlin Flow

    LiveData的粘性机制带来副作用,但这本身并不是LiveData的设计缺陷,而是对它的过度使用。 Kotlin Flow是基于kotlin的一套异步数据流框架,可以用于异步返回多个值。...支持,对Channel的收集需要开启中可以切换上下文从而实现线程切换。 观察者非活跃状态下是否还会消费事件?...也可以使用repeatOnLifecycle(State) 来在UI层收集,当生命周期 < State时,取消协,恢复时再重新启动。...例如当Activity使用repeatOnLifecycle方法启动去消费ViewModel持有的Channel里的事件消息,当前Activity因为处于STOPED状态而取消了。...,如果想要Activity在非活跃状态下直接丢弃收到的事件,应该使用repeatOnLifecycle来控制的开启和取消而非挂起。

    3.2K20

    破解 Kotlin (8) - Android 篇

    当然,Anko 这么做的根本原因在于 OnClickListener 根本拿不到有生命周期加持的作用域。不用 GlobalScope 就无法启动,怎么办?...3.2 版 AutoDisposable 当然除了直接使用一个合适的作用域来启动程之外,我们还有别的办法来确保及时被取消。...window 上撤下来的时候,我们的就会收到 cancel 的指令,尽管这种情况下的执行不会跟随 Activity 的 onDestroy 而取消,但它与 View 的点击事件紧密结合,即便 Activity...没有被销毁, View 本身被移除时也直接将监听中的取消掉。...上,结果返回时帮我们切回到主线程——这非常类似 Nodejs 这样的单线程的工作模式。

    1.1K31

    Kotlin | 是什么?

    很高兴,你终于追寻这个问题了,也许你正感到迷茫,各路大神对的理解不一,有人说它是线程框架,有人说它比线程更轻,希望我这篇博文可以帮你另一个角度简单理解。...所以我希望大家刚入手时,多语言角度去理解。 那么,是什么? 就是一个基于Kotlin语法的异步框架,它可以使开发者以同步的方式,写成异步的代码,而无需关注多余操作。...启动一个 suspend fun main() { GlobalScope.launch { println("启动--${System.currentTimeMillis(...所谓的非阻塞,其实就是切换了线程,观察打印日志变化,我们可以发现,当我们直接 GlobalScope.launch 启动一个时,此时运行的线程为默认的线程,所以被称为非阻塞的实现方式。...,使用者的角度入手,带着大家侧面去理解,希望大家都能有自己的理解。

    57910

    实战 | 使用 Kotlin Flow 构建数据流 管道

    △ 铺设管道 在 Android 应用中您可以简单地在每次需要时请求数据,例如我们可以使用挂起函数来实现在每次视图启动时向 ViewModel 请求数据,而后 ViewModel 又向数据层请求数据,接下来这一切又在相反的方向上发生...repeatOnLifecycle 是一个接收 Lifecycle.State 作为参数的挂起函数,该 API 具有生命周期感知能力,所以能够在当生命周期进入响应状态时自动使用传递给它的代码块启动新的...在上面的例子中,我们使用了 Activity 的 lifecycleScope 来启动,由于 repeatOnLifecycle 是挂起函数,所以它需要在中被调用。...API 之前您可能已经以其他方式 Android 界面中收集数据流,例如像上面的代码一样直接 lifecycleScope.launch 启动中收集,虽然这样看起来也能工作但不一定安全,因为这种方式将持续数据流中收集数据并更新界面元素...当设备旋转或者接收到配置变更时,所有的 Activity 都可能重启但 ViewModel 却能被保留,因此您不能把任意数据流都简单地 ViewModel 中暴露出来。

    1.4K10

    安卓软件开发-手把教讲解Kotlin

    二、lifecycleScope.launch 2.1 使用场景 lifecycleScope.launch 是 Android 开发中常用的启动方法,专门用于 Activity or Fragment...它的主要优势在于,当生命周期结束时,自动取消,避免内存泄漏。...2.2 基本用法 在 Activity or Fragment 中,使用 lifecycleScope 启动: import androidx.appcompat.app.AppCompatActivity...} } 会在User点击按钮时启动,getData() 模拟一个耗时任务,返回的数据会在 1 秒后更新到TextView上。 虽然Activity 被销毁,自动取消,避免潜在的内存泄漏。...通过lifecycleScope.launch和launchWhenResumed,开发者可以轻松把与生命周期绑定,确保任务在合适的时间启动和取消。

    24950

    Android面试题之Kotlin一文搞定

    基于线程,是轻量级的线程 作用 处理耗时任务,这种任务常常会阻塞主线程 保证主线程安全,即确保安全地主线程调用任何suspend函数 特点 让异步逻辑同步化 最核心的点就是,函数或者一段程序能够被挂起...可以取消任务、追踪任务、失败时发出错误信号 作用域CoroutineScope 可以追踪所有,也可以取消协 GlobalScope:生命周期是Process级别,即使Activity或Fragment...lifecycleScope:只能在Activity、Fragment中使用,绑定Activity、Fragment的生命周期 构建器 launch和async构建器都用来启动 launch...当所有子都完成后,进入已取消(Cancelled)状态,此时isCompleted=true 完成,可能是正常完成,也可能是被取消了 等待一个作业 由launch启动用join()方法...CoroutineScope()有自己的作用域上下文 都能够进行解构化并发,可以很好的管理多个子 的取消 取消作用域取消它的子 被取消的子不会影响其余兄弟 通过抛出一个特殊的异常

    16610

    【Kotlin 启动 ② ( 多程控制 | launch 执行顺序控制 | Job#join() 函数 | async 执行顺序控制 | Deferred#await() 函数 )

    87183425 一、launch 执行顺序控制 ---- 如果需要通过 launch 构建器 启动多个协 , 后面的需要等待前面的执行完毕 , 在启动靠后的 , 实现方案如下 :...调用 launchJob.join() 函数挂起 , 该 launchJob 任务执行完毕后 , 才会执行后面的 launch 任务 ; runBlocking { // 调用...* * 特别是,它意味着父在子上调用' join '时抛出 * [CancellationException]如果子进程失败,因为子进程的失败默认取消父进程, * 除非子进程是[supervisor...---- 如果需要通过 async 构建器 启动多个协 , 后面的需要等待前面的执行完毕 , 在启动靠后的 , 实现方案如下 : 调用 Deferred#await() 函数 , 可以挂起...() 函数挂起 , 该 asyncDeferred 任务执行完毕后 , 才会执行后面的 async 任务 ; runBlocking { // 调用 runBlocking 函数

    98320

    【Kotlin 底层实现 ③ ( 结构化并发 | MainScope 作用域 | 取消协作用域 | Activity 实现 CoroutineScope 作用域接口 )

    文章目录 一、MainScope 作用域 二、取消 MainScope 作用域 三、Activity 实现 CoroutineScope 作用域接口 常见的 CoroutineScope...作用域 : GlobalScope : 该作用域是 进程级别的 , 与应用进程同级 , 即使 Activity 被销毁 , 任务也可以继续执行 ; MainScope : 该 作用域仅在 Activty...生命周期绑定 ; lifecycleScope : 该作用与仅在 Activity 中使用 , 与 Activity 生命周期绑定 ; 一、MainScope 作用域 ---- MainScope...是任务调度器 , 执行挂起函数 , 系统自动分配一个 任务调度器 ; 二、取消 MainScope 作用域 ---- 调用 MainScope 作用域 的 cancel 函数 , 即可取...启动任务 , 如果取消 mainScope 作用域 , 则在该 作用域 中执行的 任务 , 都会被取消 ; 挂起函数中途被取消 抛出 JobCancellationException

    1.3K11

    【Kotlin 底层实现 ② ( 调度器 | 任务泄漏 | 结构化并发 )

    ---- 任务泄漏 : 发起 任务 后 , 无法追踪任务的执行结果 , 任务等于无效任务 , 但是仍然消耗 内存 , CPU , 网络 , 磁盘 等资源 ; Kotlin 中引入了 结构化并发机制...: 追踪正在执行的任务 ; 发出错误信号 : 如果 任务执行失败 , 发出错误信号 , 表明执行任务出错 ; 任务 运行时 , 必须指定其 CoroutineScope 作用域 , 其追踪所有的...任务 , CoroutineScope 作用域 可以取消 所有由其启动任务 ; 常见的 CoroutineScope 作用域 : GlobalScope : 该作用域是 进程级别的..., 与应用进程同级 , 即使 Activity 被销毁 , 任务也可以继续执行 ; MainScope : 该 作用域仅在 Activty 中 , 如果 Activity 被销毁 , 则 在 onDestory...Activity 中使用 , 与 Activity 生命周期绑定 ;

    65320

    知识点 | ViewModel 四种集成方式

    Activity 和 Fragment 通常会在下面三种情况下被销毁: 当前界面永久离开: 用户导航至其他界面或直接关闭 Activity (通过点击返回按钮或执行的操作调用了 finish() 方法...如果您不了解,这里有一系列很棒的博客《在 Android 开发中使用》以及 codelab: 在 Android 应用中使用 Kotlin 以供参考。...() } 复制代码 这段示例代码只启动了一个,但我们在真实的使用环境下很容易创建出许多,这就难免导致有些的状态无法被跟踪。...CoroutineScope 可以持续跟踪的执行,它可以被取消。当 CoroutineScope 被取消时,它所跟踪的所有都会被取消。...这样一来,只要您使用了 ViewModel,您就可以使用 viewModelScope 在 ViewModel 中启动各种,而不用担心任务泄漏。

    2.5K20

    Kotlin 的上下文和调度器介绍-Dispatchers

    :默认情况下,它将会启动它的对象中继承上下文以及调度器。 我们上面的例子就是,main线程中的runBlocking对象中继承了上下文,结果显示运行在了main线程之中。...") } //输出 job1: 我运行在GlobalScope启动中 job2: 我是一个父启动的子对象 job1: 等待了1秒,你会发现我不受取消方法的影响 main: 整个协全部取消后...而我们如果在Android开发中,使用Activity启动一个来处理网络或者异步IO读取等操作。所有的这个协应该在Activity被销毁后自动取消,来避免内存泄露。...,自动进行关闭。...Android 现在在所有具有生命周期的实体中(activity,Fragment等),都对作用域提供了一级支持。 局部数据传递 我们如果使用,特别是子,父混杂等等情况。

    43510

    利用Kotlin的实现简单的异步加载详解

    lauch()创建并启动了一个,这儿的参数Background是一个CoroutineContext对象,确保这个协运行在一个后台线程,确保你的应用程序不会因耗时操作而阻塞和崩溃。...在第一个里边我们又调用了launch(UI)创建并启动了一个新的,这儿的UI并不是我们自己创建的,他是Kotlin在Android平台里边预定义的一个CoroutineContext,代表着在UI...它的意思是不会立即启动一个。直到你显示的请求他返回一个值的时候它才会启动,稍后你会看到具体怎样做。这个协返回了一个Deferred<T 对象到调用者。...当值其他中返回的时候,他将被唤醒并将值Deferred传递到这个lambda中。挂起函数(Suspending functions)是中最主要的概念。...一旦Activity的onDestroy方法被调用的时候,我们在load()函数中添加的lifecycle观察者将会取消第一个,也会使第二个被取消,避免block()被调用。

    2.1K20

    【Kotlin 启动 ⑤ ( 作用域构建器 | runBlocking 函数 | coroutineScope 函数 | supervisorScope 函数 )

    底层实现 ② ( 调度器 | 任务泄漏 | 结构化并发 ) 【Kotlin 底层实现 ③ ( 结构化并发 | MainScope 作用域 | 取消协作用域 | Activity...: 任务 运行时 , 必须指定其 CoroutineScope 作用域 , 其 追踪所有的 任务 , CoroutineScope 作用域 可以 取消 所有由其启动任务 ; 结构化并发..., 将 主线程 或 子线程 包装成 体 , 在该中执行 任务 , 阻塞当前的线程 ; 函数原型如下 : public actual fun runBlocking(context...该会在另外的独立的线程执行 任务 , 不会干扰当前启动的线程 ; 函数原型如下 : public suspend fun coroutineScope(block: suspend...示例 coroutineScope 函数 构建的 作用域 代码示例 : 并发执行两个协 , 取消其中一个 , 另外一个自动取消 ; package kim.hsl.coroutine

    53130

    扫码

    添加站长 进交流群

    领取专属 10元无门槛券

    手把手带您无忧上云

    扫码加入开发者社群

    相关资讯

    热门标签

    活动推荐

      运营活动

      活动名称
      广告关闭
      领券