继续我学习 Android 的尝试,我只是阅读以下内容 :
问题: 用户是否可以选择终止应用程序,除非我们使用菜单选项来杀死它?如果不存在这样的选项,用户如何终止该应用程序?
答案:(Romain Guy): 用户没有,系统会自动处理。这就是活动生命周期(特别是 onPause / onStop / onDestroy)的用途。无论你做什么,都不要放 “退出” 或 “退出” 应用程序按钮。它与 Android 的应用程序模型无关。这也与核心应用程序的工作方式相反。
呵呵,我在 Android 世界中采取的每一步都会遇到某种问题 =(
显然,你无法在 Android 中退出应用程序(但 Android 系统可以很好地完全破坏你的应用程序)。那是怎么回事?我开始认为编写一个充当 “普通应用程序” 的应用程序是不可能的 - 用户可以在他 / 她决定这样做时退出应用程序。这不应该依赖操作系统来做。
我尝试创建的应用程序不是 Android Market 的应用程序。它不是一般公众 “广泛使用” 的应用程序,它是一个将用于非常狭窄的业务领域的商业应用程序。
我实际上真的很期待为 Android 平台开发,因为它解决了 Windows Mobile 和. NET 中存在的许多问题。然而,上周对我来说有点懈怠... 我希望我不必放弃 Android,但它现在看起来不太好 =(
有没有办法让我真的退出申请?
这最终会回答你的问题,但我首先要解决你在各种意见中提出的一些问题,以及撰写本文时已经给出的各种答案。我无意改变你的想法 - 相反,这些是为了将来读这篇文章的其他人。
关键是我无法让 Android 确定何时终止我的应用程序。这必须是用户的选择。
数百万人对模型非常满意,因为环境会根据需要关闭应用程序。这些用户根本不考虑 “终止”Android 应用程序,而不是考虑 “终止” 网页或 “终止” 恒温器。
iPhone 用户的方式大致相同,因为按下 iPhone 按钮不一定 “感觉” 就像应用程序被终止一样,因为许多 iPhone 应用程序都会在用户停止的地方启动,即使应用程序确实已关闭(因为仅限 iPhone)目前允许一个第三方应用程序。
正如我上面所说,我的应用程序中发生了很多事情(数据被推送到设备,列表中的任务总是存在,等等)。
我不知道 “列出任务总是应该在那里” 是什么意思,但 “推送到设备的数据” 是一个令人愉快的小说,在任何情况下都不应该由活动完成。使用计划任务(通过AlarmManager
)更新数据以获得最大可靠性。
我们的用户每次拨打电话时都会登录并且无法执行此操作,并且 Android 决定终止该应用。
有许多 iPhone 和 Android 应用程序可以解决这个问题。通常,这是因为它们保留登录凭据,而不是强制用户每次手动登录。
例如,我们想在退出应用程序时检查更新
这是任何操作系统的错误。如您所知,您的应用程序被 “退出” 的原因是操作系统正在关闭,然后您的更新过程将在流中失败。一般来说,这不是一件好事。检查启动时的更新或完全异步检查更新(例如,通过计划任务),从不退出。
一些评论表明,按下后退按钮并不会杀死应用程序(请参阅上面的问题中的链接)。
按 BACK 按钮不会 “杀死应用程序”。当用户按下 BACK 按钮时,它完成屏幕上的活动。
它应该只在用户想要终止它时终止 - 从来没有任何其他方式。如果您无法编写 Android 中的行为类似的应用程序,那么我认为 Android 不能用于编写真实应用程序 =(
那么 Web 应用程序也不行。或者WebOS ,如果我正确理解他们的模型(还没有机会玩一个)。在所有这些中,用户不会 “终止” 任何东西 - 他们只是离开。 iPhone 有点不同,因为它目前只允许一次运行(少数例外),因此离开行为意味着应用程序立即终止。
有没有办法让我真的退出申请?
正如其他人告诉你的那样,用户(通过 BACK)或你的代码(通过finish()
)可以关闭你当前正在运行的活动。对于正确编写的应用程序,用户通常不需要任何其他东西,只需要使用 “退出” 选项来使用 Web 应用程序。
根据定义,没有两个应用程序环境是相同的。这意味着当新的环境出现而其他环境被埋没时,您可以看到环境趋势。
例如,试图消除 “文件” 概念的行动越来越多。大多数 Web 应用程序不会强制用户考虑文件。 iPhone 应用程序通常不会强迫用户考虑文件。 Android 应用程序通常不会强迫用户考虑文件。等等。
同样,越来越多的人试图消除 “终止” 应用程序的概念。大多数 Web 应用程序不会强制用户注销,而是在一段时间不活动后隐式地将用户注销。与 Android 相同,在较小程度上,iPhone(可能还有 WebOS)也是如此。
这需要更多地强调应用程序设计,关注业务目标,而不是坚持与先前应用程序环境相关的实现模型。缺乏时间或倾向于这样做的开发人员会因为破坏现有心理模型的新环境而感到沮丧。这不是任何一种环境的错,不仅仅是因为风暴在它周围流动而不是通过风暴的山脉的错误。
例如,一些开发环境,如Hypercard和 Smalltalk,将应用程序和开发工具混合在一个设置中。除了应用程序的语言扩展之外,这个概念并没有引起太多关注(例如, Excel 中的 VBA ,AutoCAD 中的 Lisp )。因此,想出应用程序本身存在开发工具的心理模型的开发人员要么必须改变他们的模型,要么将自己限制在他们的模型适用的环境中。
所以,当你写:
除了我发现的其他混乱的东西,我认为开发我们的 Android 应用程序是不会发生的。
对你来说,这对你来说似乎是最好的。同样,我会建议您不要尝试将应用程序移植到 Web 上,因为您在 Android 应用程序中报告的某些问题也会在 Web 应用程序中找到(例如,没有 “终止”)。或者反过来说,如果有一天你做端口您的应用程序到 Web,您可能会发现 Web 应用程序的流量可能是针对 Android 更好的匹配,你可以在那时再讲一个 Android 端口。
我想在这里为这个帖子的未来读者添加一个更正。这种特殊的细微差别已经逃脱了我的理解很长一段时间,所以我想确保你们没有犯同样的错误:
如果堆栈上有多个活动, System.exit()
不会System.exit()
您的应用程序。实际发生的是, 进程被杀死并立即重新启动 ,堆栈上只有少量活动。这也是当您的应用程序被 “强制关闭” 对话框杀死时,甚至当您尝试从 DDMS 终止该进程时发生的情况。据我所知,这是一个完全无证的事实。
简短的回答是,如果你想退出你的应用程序,你必须跟踪你的堆栈中的所有活动,并在用户想要退出时finish()
所有这些活动(并且没有,没有办法迭代活动堆栈,所以你必须自己管理所有这些)。即使这实际上并没有杀死你可能拥有的过程或任何悬空参考。它只是完成了活动。另外,我不确定Process.killProcess(Process.myPid())
是否更好; 我没有测试过。
另一方面,如果您可以在堆栈中保留活动,那么还有另一种方法可以使您的工作变得非常简单: Activity.moveTaskToBack(true)
将简单地显示您的进程并显示主屏幕。
长期答案涉及对这种行为背后的哲学的解释。哲学源于许多假设:
onSaveInstanceState
期间有效地序列化,但是 whaddya 会做什么?)对于大多数写得很好的 Android 应用程序,这应该是真的因为你永远不知道你的应用何时会在后台被杀掉。 当你考虑它时,这适用于平台。首先,这正是当进程在后台被杀死并且用户返回它时发生的情况,因此需要在它停止的地方重新启动它。其次,这是当应用程序崩溃并呈现可怕的强制关闭对话框时发生的情况。
说我希望我的用户能够拍照并上传。我从我的活动中启动了 Camera Activity,并要求它返回一张图片。 Camera 被推到我当前 Task 的顶部(而不是在自己的 Task 中创建)。如果相机出现错误并且崩溃,是否会导致整个应用程序崩溃?从用户的角度来看,只有相机失败,应该将它们返回到之前的活动。所以它只是重新启动进程,堆栈中的所有相同活动,减去相机。由于你的活动应该被设计成可以在帽子上被杀死和恢复,这应该不是问题。不幸的是,并非所有应用程序都可以这样设计,因此无论 Romain Guy 或其他任何人告诉您,这对我们许多人来说都是一个问题。因此,我们需要使用变通方法。
所以,我的结论是:
finish()
或调用moveTaskToBack(true)
。 Intent.FLAG_ACTIVITY_CLEAR_TOP
标志的 Intent 调用startActivity()
。 我的所有应用程序都退出了按钮...... 由于这个原因,我经常得到用户的积极评价。我不关心平台是否以应用程序不需要它们的方式设计。说 “不要把它们放在那里” 有点荒谬。如果用户想要退出... 我向他们提供了完全相同的访问权限。我认为它根本不会降低 Android 的运行方式,这似乎是一种很好的做法。我了解生命周期...... 我的观察是 Android 在处理它方面做得不好.... 这是一个基本事实。