完成旧的活动并开始新的活动,反之亦然


79

我知道,两个代码段的结果相同

finish();
startActivity(newActivity);

startActivity(newActivity);
finish();

我想知道您的意见,如果两者之间有很大差异。这个比那个好吗?如果是这样,为什么?

Answers:


61

当您执行startActivity()时,所有要做的就是将您的意图发布到事件队列中。活动的实际开始在不久的将来会异步发生。因此,我认为两者之间没有太大区别。


1
这对我也听起来很合理
Tima 2010年

6
动画对我来说是不同的。请参阅下面的答案。
Monstieur

但是方法是完全错误的。对于此用例,实际上存在一些标志(用于清单中的意图)。
Ewoks 2015年

@Ewoks请走,什么意思,哪个标志?
安东尼

3
实际上,应用程序任务行为存在很大差异。我在一个单独的答案中阐述了这个问题。
Vit Khudenko

26

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


16

根据和调用的顺序,应用程序任务行为之间存在重要差异。startActivity()finish()

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

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

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

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

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

这是在某些情况下可能出问题的转折点。

综上所述,如果您想站在安全的一边(而不是FLAG_ACTIVITY_NEW_TASK被添加到Intent上而不会遇到意外的副作用),那么命令必须是:

  • startActivity()
  • finish()

演示项目

屏幕录像:


查看源代码,Activity.startActivity()最终调用ActivityThread.sendActivityResult(),后者依次调用scheduleSendResult(),后者仅将活动添加到队列中。线程稍后将对其进行处理。另一方面,finish()调用ActivityManagerNative.finishActivity()立即结束活动。
伊曼纽尔

@Emmanuel,我无法弄清您的陈述是否与我所描述的问题有关。:)
Vit Khudenko

9

除了伊曼纽尔人的答案:

这两种方法startActivityfinish将被调度之后调用方法的结束,因为两者都是由UI线程处理。


7

我会做第二个选择,我不会在官方提供的任何内容上支持此操作,但是在结束之前启动新活动更有意义,这样新活动会通过意图弹出,现在的后台活动可以调用其所有清理方法。

如果您要反过来做,则可能是意图在清理完成之前没有时间开火。即活动将在finish()调用之后调用startActivity()吗?

希望您理解我要说明的内容,为了安全起见,我会选择第二种方法。


是的,我了解您的想法。听起来合乎逻辑。但是我无法想象我,什么时候可能出现这种情况
蒂玛,2010年

2

我有类似的问题:

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();

一切似乎正常,活动A可见。

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


当您完成应用程序的finish()时,android从堆栈中拉出LRU活动,该活动为B。此外,这使我认为finish()是即时的而不是异步的。
MehmetAVŞAR2014年

0

我通常会startActivity()先这样做,finish()因为我认为要确保新屏幕在前一个屏幕出现之前就已出现。

我的应用程序中有一个登录页面。用户成功登录后,登录活动消失,主要活动启动。它在Android 4中正常工作。

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

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在手机日志中启动时,我的应用会占用许多资源。我没有什么,mainActivity只是它是默认的“材料设计”布局。

我撤消了订单,现在我的手机可以正常运行了。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.