继续学习Android,我读了以下内容:

Question: Does the user have a choice to kill the application unless we put a menu option in to kill it? If no such option exists, how does the user terminate the application? Answer: (Romain Guy): The user doesn't, the system handles this automatically. That's what the activity lifecycle (especially onPause/onStop/onDestroy) is for. No matter what you do, do not put a "quit" or "exit" application button. It is useless with Android's application model. This is also contrary to how core applications work.

呵呵,我在Android世界里每走一步都会遇到一些问题=(

显然,你不能在Android中退出应用程序(但Android系统可以随时完全销毁你的应用程序)。这是怎么回事?我开始认为这是不可能写一个应用程序的功能作为“正常的应用程序”-用户可以退出应用程序时,他/她决定这么做。这不应该依靠操作系统来完成。

我正在尝试创建的应用程序不是Android市场的应用程序。它不是一个被大众“广泛使用”的应用程序,它是一个将在非常狭窄的商业领域使用的商业应用程序。

我其实很期待为Android平台开发,因为它解决了Windows Mobile和。net中存在的许多问题。然而,上周对我来说有点令人失望……我希望我不必放弃Android,但它现在看起来不太好=(

有办法让我真的退出应用程序吗?


当前回答

我只是想在这里为这篇文章的未来读者补充一个更正。这个细微的差别我已经不理解很长一段时间了,所以我想确保你们没有人会犯同样的错误:

如果栈上有多个activity, System.exit()不会杀死你的应用。实际发生的情况是进程被杀死,并立即重新启动,堆栈上少了一个活动。当你的应用程序被强制关闭对话框杀死时,甚至当你试图从DDMS中杀死进程时,也会发生这种情况。据我所知,这是一个完全没有记录的事实。

The short answer is, if you want to exit your application, you've got to keep track of all activities in your stack and finish() ALL of them when the user wants to exit (and no, there is no way to iterate through the Activity stack, so you have to manage all of this yourself). Even this does not actually kill the process or any dangling references you may have. It simply finishes the activities. Also, I'm not sure whether Process.killProcess(Process.myPid()) works any better; I haven't tested it.

另一方面,如果你可以将活动保留在堆栈中,还有另一个方法可以让事情变得超级简单:Activity.moveTaskToBack(true)将简单地将你的进程作为背景并显示主屏幕。

长的答案包括对这种行为背后的哲学的解释。这一理论是基于以下几个假设:

First of all, this only happens when your app is in the foreground. If it is in the background the process will terminate just fine. However, if it is in the foreground, the OS assumes that the user wants to keep doing whatever he/she was doing. (If you are trying to kill the process from DDMS, you should hit the home button first, and then kill it) It also assumes that each activity is independent of all the other activities. This is often true, for example in the case that your app launches the Browser Activity, which is entirely separate and was not written by you. The Browser Activity may or may not be created on the same Task, depending on its manifest attributes. It assumes that each of your activities is completely self-reliant and can be killed/restored in a moment's notice. (I rather dislike this particular assumption, since my app has many activities which rely on a large amount of cached data, too large to be efficiently serialized during onSaveInstanceState, but whaddya gonna do?) For most well-written Android apps this should be true, since you never know when your app is going to be killed off in the background. The final factor is not so much an assumption, but rather a limitation of the OS: killing the app explicitly is the same as the app crashing, and also the same as Android killing the app to reclaim memory. This culminates in our coup de grace: since Android can't tell if the app exited or crashed or was killed in the background, it assumes the user wants to return where they left off, and so the ActivityManager restarts the process.

仔细想想,这是适合这个平台的。首先,这正是当进程在后台被杀死,用户返回到它时所发生的情况,因此它需要在它停止的地方重新启动。其次,这是当应用程序崩溃并呈现可怕的强制关闭对话框时所发生的情况。

Say I want my users to be able to take a picture and upload it. I launch the Camera Activity from my activity, and ask it to return an image. The Camera is pushed onto the top of my current Task (rather than being created in its own Task). If the Camera has an error and it crashes, should that result in the whole app crashing? From the standpoint of the user, only the Camera failed, and they should be returned to their previous activity. So it just restarts the process with all the same Activities in the stack, minus the Camera. Since your Activities should be designed so that they can be killed and restored at the drop of a hat, this shouldn't be a problem. Unfortunately, not all apps can be designed that way, so it is a problem for many of us, no matter what Romain Guy or anyone else tells you. So, we need to use workarounds.

所以,我最后的建议是:

Don't try to kill the process. Either call finish() on all activities or call moveTaskToBack(true). If your process crashes or gets killed, and if, like me, you need the data that was in memory which is now lost, you'll need to return to the root activity. To do this, you should call startActivity() with an Intent that contains the Intent.FLAG_ACTIVITY_CLEAR_TOP flag. If you want to kill your app from the Eclipse DDMS perspective, it had better not be in the foreground, or it will restart itself. You should press the Home button first, and then kill the process.

其他回答

回答:(罗曼盖伊):用户不需要,系统会处理这个问题 自动。这就是活动生命周期(特别是 onPause/onStop/onDestroy)用于。无论你做什么,都不要放不下 “退出”或“退出”应用程序按钮。这在安卓系统中毫无用处 应用程序模型。这也与核心应用程序的方式相反 工作。

1: Totally exiting an application may be generally unmandatory, but it is not useless. What if windows had no exit option? System would be doggy slow as memory was full and the OS had to guess at which programs you were done with. I don't care what Romain Guy or even Larry Page and Sergey Brin say - these are unquestionable facts: Systems run slower when they have to kill tasks to get their memory before a new app can be launched. You just can't tell me that it doesn't take time to kill an app! Even the light from distant stars take time... There is some use in allowing the user to fully close apps.

2:与核心应用程序的工作方式相反?这是什么意思?当我现在运行一个应用程序时,它不再做任何工作……它只是在需要内存时等待被操作系统杀死。

总而言之,最小化和退出之间有明显的区别,两者都不适合对方。每个螺丝上都留个螺丝刀吗?还是每扇门都有钥匙?我们是不是把所有的电器都开着,直到断路器爆炸,我们需要打开另一个电器?我们是不是把洗碗机里装满了盘子,每次只拿出足够的空间来放一些新的脏盘子?我们把所有的车都停在车道上,直到——哦,算了。

如果用户想要最小化应用程序,那么最好的方法就是最小化它。如果用户想要退出应用程序,那么无论如何最好是退出。

这会让人皱眉吗?这是Android的观点——他们不赞成。许多独立的Android新手开发者对此表示不满。

但当它落到实处时,有好的编码和坏的编码。有好的程序流模型也有坏的程序流模型。

当用户知道他们已经用完了程序时,把程序留在内存中并不是好的程序流程。它完全没有任何用处,而且在启动新应用程序或运行应用程序分配更多内存时,它会减慢运行速度。

这有点像你的汽车:有时你让它一直开着,比如在红绿灯前停车,或者在快餐店经过时停车,或者在自动取款机前停车。但在其他情况下,你确实想把它关掉——比如当你去工作的时候,或者在杂货店,甚至在家里。

同样地,如果你正在玩游戏,这时手机响了。暂停游戏并继续运行。但如果用户已经玩了一段时间,那就让他们退出游戏吧。

The exit button on some applications should be more out in front than others. Games, for example, or programs where the user is likely to want to fully exit, should have an obvious exit. Other programs, like, perhaps, email programs, where exiting is an unlikely desire (so that it can keep checking for email) -- these programs should not waste prime control input screen space with an exit option, but for good program flow, it should have an exit option. What if someone decides they don't want their mail program trying to check email when they are in poor coverage area, or maybe in a Skype call or whatever? Let them exit the email program if they want!

暂停和退出是两项至关重要的任务,两者都不能实现对方的作用。

这很简单。只要遵循我要告诉你的这些指示:

比如你有多个活动,从一个活动到另一个活动。你可能会像这样使用intent:

Intent i1 = new Intent(this, AnotherActivity);
startActivity(i1) 

你只需要添加finish();例如,从头到尾在每个活动上启动intent活动后,

Intent i1=new Intent(this, AnotherActivity);
startActivity(i1) 
finish();

所以当你点击退出按钮时使用的是finish()或System.exit(0)必须完全关闭你的应用程序。

Linux内核有一个称为内存不足杀手的特性(如上所述,这些策略可以在用户空间级别进行配置,而且内核不是最优的,但也不是不必要的)。

它被Android大量使用:

OOM杀手不适合用户空间 Android笔记(OOM杀手信息-你可以在Android上配置OOM功能) Android移植在Real Target

一些用户空间应用程序可以帮助这些杀死应用程序,例如:

自动杀手/配置Android内部任务杀手

我只是想在这里为这篇文章的未来读者补充一个更正。这个细微的差别我已经不理解很长一段时间了,所以我想确保你们没有人会犯同样的错误:

如果栈上有多个activity, System.exit()不会杀死你的应用。实际发生的情况是进程被杀死,并立即重新启动,堆栈上少了一个活动。当你的应用程序被强制关闭对话框杀死时,甚至当你试图从DDMS中杀死进程时,也会发生这种情况。据我所知,这是一个完全没有记录的事实。

The short answer is, if you want to exit your application, you've got to keep track of all activities in your stack and finish() ALL of them when the user wants to exit (and no, there is no way to iterate through the Activity stack, so you have to manage all of this yourself). Even this does not actually kill the process or any dangling references you may have. It simply finishes the activities. Also, I'm not sure whether Process.killProcess(Process.myPid()) works any better; I haven't tested it.

另一方面,如果你可以将活动保留在堆栈中,还有另一个方法可以让事情变得超级简单:Activity.moveTaskToBack(true)将简单地将你的进程作为背景并显示主屏幕。

长的答案包括对这种行为背后的哲学的解释。这一理论是基于以下几个假设:

First of all, this only happens when your app is in the foreground. If it is in the background the process will terminate just fine. However, if it is in the foreground, the OS assumes that the user wants to keep doing whatever he/she was doing. (If you are trying to kill the process from DDMS, you should hit the home button first, and then kill it) It also assumes that each activity is independent of all the other activities. This is often true, for example in the case that your app launches the Browser Activity, which is entirely separate and was not written by you. The Browser Activity may or may not be created on the same Task, depending on its manifest attributes. It assumes that each of your activities is completely self-reliant and can be killed/restored in a moment's notice. (I rather dislike this particular assumption, since my app has many activities which rely on a large amount of cached data, too large to be efficiently serialized during onSaveInstanceState, but whaddya gonna do?) For most well-written Android apps this should be true, since you never know when your app is going to be killed off in the background. The final factor is not so much an assumption, but rather a limitation of the OS: killing the app explicitly is the same as the app crashing, and also the same as Android killing the app to reclaim memory. This culminates in our coup de grace: since Android can't tell if the app exited or crashed or was killed in the background, it assumes the user wants to return where they left off, and so the ActivityManager restarts the process.

仔细想想,这是适合这个平台的。首先,这正是当进程在后台被杀死,用户返回到它时所发生的情况,因此它需要在它停止的地方重新启动。其次,这是当应用程序崩溃并呈现可怕的强制关闭对话框时所发生的情况。

Say I want my users to be able to take a picture and upload it. I launch the Camera Activity from my activity, and ask it to return an image. The Camera is pushed onto the top of my current Task (rather than being created in its own Task). If the Camera has an error and it crashes, should that result in the whole app crashing? From the standpoint of the user, only the Camera failed, and they should be returned to their previous activity. So it just restarts the process with all the same Activities in the stack, minus the Camera. Since your Activities should be designed so that they can be killed and restored at the drop of a hat, this shouldn't be a problem. Unfortunately, not all apps can be designed that way, so it is a problem for many of us, no matter what Romain Guy or anyone else tells you. So, we need to use workarounds.

所以,我最后的建议是:

Don't try to kill the process. Either call finish() on all activities or call moveTaskToBack(true). If your process crashes or gets killed, and if, like me, you need the data that was in memory which is now lost, you'll need to return to the root activity. To do this, you should call startActivity() with an Intent that contains the Intent.FLAG_ACTIVITY_CLEAR_TOP flag. If you want to kill your app from the Eclipse DDMS perspective, it had better not be in the foreground, or it will restart itself. You should press the Home button first, and then kill the process.

您可以通过按Back按钮或在Activity中调用finish()来退出。如果您想显式地终止它,只需从MenuItem调用finish()。

Romain并不是说不能这样做,只是说这样做毫无意义——用户不需要关心是否退出或保存他们的工作,因为应用程序生命周期的工作方式鼓励您编写智能软件,无论发生什么都能自动保存和恢复其状态。