【问题标题】:Finish old activity and start a new one or vice versa完成旧活动并开始新活动,反之亦然
【发布时间】:2010-11-15 08:56:19
【问题描述】:

我知道,我使用两个代码 sn-ps 得到相同的结果

finish();
startActivity(newActivity);

startActivity(newActivity);
finish();

我想知道你的意见,如果他们之间有很大的不同。这个比那个好吗?如果有,为什么?

【问题讨论】:

  • 这里都可以,但是动画完全不同。

标签: android android-activity


【解决方案1】:

当您执行 startActivity() 时,所做的只是将您的意图发布到事件队列中。活动的实际开始在不久的将来异步发生。所以我看不出两者有什么大的区别。

【讨论】:

  • 这听起来对我来说也很明智
  • 动画对我来说是不同的。请参阅下面的答案。
  • 但是方法是完全错误的。这个用例实际上存在一些标志(用于意图以及清单中)。
  • 就我而言,这完全不同。活动 A (singleTop) 调用活动 B (默认)。如果我从 B -> startActivity 开始并完成,则调用 A onCreate。另一方面,如果我从 B -> 完成并开始活动,则调用 A onNewIntent。巨大的差异取决于定义的活动启动模式!
  • 应用任务行为其实有很大的不同。我在单独的答案中详细说明了此事。
【解决方案2】:

动画明显不同(至少从 4.1 开始)。调用finish() first 开始较早地淡出第一个活动,您可以在新活动淡入之前短暂看到黑色背景。调用startActivity() first 在旧活动之上淡入新活动,黑色背景不是可见。

【讨论】:

    【解决方案3】:

    根据startActivity()finish() 调用的顺序,应用程序task 的行为存在重要差异。

    我所描述的情况仅适用于当前活动(正在停止的活动)是任务中唯一活动的情况。

    通常,您会期望系统不会更改启动意图(您为启动另一个活动而创建的意图)。如果在调用startActivity() 之前在任务中的最后一个 活动上调用finish(),则情况并非如此。

    在这种情况下,ActivityManager 是一个系统组件,同时执行 startActivity() adds Intent.FLAG_ACTIVITY_NEW_TASK 标志到您的意图。

    当这种情况发生时,人们可能会注意到 LogCat 中的日志条目与此类似:

    W/ActivityManager:从完成调用 startActivity ActivityRecord{4a19b47 u0 com.foo.bar/com.foo.bar.SplashActivity t4928 F};强制 Intent.FLAG_ACTIVITY_NEW_TASK 用于: Intent { cmp=com.foo.bar/com.foo.bar.MainActivity }

    这是(在某些情况下)事情可能出错的转折点。

    总而言之,如果您想安全起见(而不是体验将 FLAG_ACTIVITY_NEW_TASK 添加到意图的意外副作用),那么顺序必须是:

    • startActivity()
    • finish()

    演示project.

    屏幕录像:

    【讨论】:

    • 查看源代码,Activity.startActivity() 最终调用了 ActivityThread.sendActivityResult(),后者又调用了 scheduleSendResult(),它只是将活动添加到队列中。稍后将有一个线程处理它。另一方面,finish() 调用 ActivityManagerNative.finishActivity() 立即结束活动。
    • @Emmanuel,我无法弄清楚您的陈述是否与我描述的问题有关。 :)
    【解决方案4】:

    除了伊曼纽尔的回答:

    startActivityfinish 两个方法都将在调用方法结束后调度,因为它们都由 UI 线程处理。

    【讨论】:

      【解决方案5】:

      我会做第二个选择,我不支持我从官方来源查找的任何内容,但是,在调用完成之前启动新活动更有意义,这样新活动就会弹出通过一个意图,现在的后台活动可以调用它所有的清理方法。

      如果你反其道而行之,那么在清理完成之前,意图可能没有时间触发。 IE。 Activity 会在 finish() 调用之后调用 startActivity() 吗?

      我希望你能理解我的意思,为了安全起见,我会选择第二个选项。

      【讨论】:

      • 是的,我理解你的想法。听起来很合乎逻辑。但我无法想象我,当这种情况可能发生时
      【解决方案6】:

      我有类似的问题:

      Activity A: singleInstance
      Activity B: singleInstance
      Activity C: singleInstance
      
      A starts B 
      B starts C
      C wants to start A:
      

      如果我使用这里:

      finish();
      startActivity(A);
      

      发生了一些连线事件:活动 B 而不是 A 进入前台! 但是如果我像这样更改代码:

      startActivity(A);
      finish();
      

      一切正常,Activity A 可见。

      我不知道是什么问题,但似乎在第一种情况下,C 在执行 startActivity 命令之前完成,以便 back stack 处理这种情况并显示其顶部活动为B! 但在第二种情况下,一切正常。

      【讨论】:

      • 当您完成()应用程序时,android 从堆栈中拉出 LRU 活动,即 B。此外,这让我认为 finish() 是即时的而不是异步的。
      【解决方案7】:

      我通常在finish() 之前使用startActivity(),因为我认为这样可以确保新屏幕在前一个屏幕出现之前出现。

      我的应用中有一个登录页面。用户登录成功后,登录活动消失,主要活动启动。它在 Android 4 中运行良好。

      今天我想用 Material design 重写它。但是,我遇到了一个大问题。新的 Android 工作室使用材料设计创建空白活动,我认为这需要很多资源。同样的过程,但我得到了错误

      11-26 18:20:44.450 18397-18397/? I/Choreographer: Skipped 42 frames!  The application may be doing too much work on its main thread.
      11-26 18:20:44.485 18397-18408/? I/art: Background partial concurrent mark sweep GC freed 2864(191KB) AllocSpace objects, 4(43MB) LOS objects, 13% free, 100MB/116MB, paused 8.056ms total 39.767ms
      

      mainActivity 在我的手机 logcat 中启动时,它说我的应用程序占用了很多资源。我在 mainActivity 中没有任何内容,只是它是默认的 Material Design 布局。

      我颠倒了订单,现在它可以在我的手机上正常运行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-15
        • 2011-09-06
        • 2020-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多