Android程序的退出功能

来源:互联网 发布:淘宝购物返利网哪个好 编辑:程序博客网 时间:2024/04/29 04:29

搞Android开发有一段时间了,相信很多从Windows开发过来的Android程序员都习惯性地会跟我一样遇到过同一个问题:如何彻底退出程序?这里说下我自己的经验,并不权威,仅供参考。

 

一开始我也上网到处找退出的资料,网上这方面的文章也是很多,总结下来退出Android程序的方法大概有以下几种:

1.直接调System.exit(0)或直接用android.os.Process.killProcess;
2.调用ActivityManager.restartPackage或killBackgroudProcesses;
3.搞个Activity堆栈列表,把所有Activity通过继承基类或调用函数的方式记录下来,退出时逐一finish;
4.故意制造致命错误,然后利用错误强制退出;
5.搞一个singleTop的根Activity,通过它自动清除Activity堆栈再退出;
6.调用隐藏的ActivityManager.forceStopPackage方法

不过这些方法经过试验基本上都不完美,要不就是退不干净,要不就是只支持2.2以下旧版,要不就是要求ROOT权限。其中System.exit(0)和android.os.Process.killProcess能结束当前Activity,有时候能结束当前Activity和上一个Activity,但再多的话基本上就不行了。

相对比较完美的就是自己做Activity堆栈列表来释放了,有一段时间我也采用了这一方法,觉得不错,问题好像是解决了,不过解决得相当难受,自己做Activity堆栈,意味着每个Activity都要继承同一个父类。我一边调试程序一边咒骂谷歌,你乍就不能提供个好用的退出接口?

好景不长,没多久我发现,程序只把Activity结束了,但程序并没有退出,后台还有几个线程在跑,退出后过了好久还会提示出错,真是气死人不偿命。我想要求程序退出前等待线程一下吧,结果发现那几个线程并非是我自己创建的,而是用了第三方的一个地图组件在后台下载数据。最后我出了个毛招,把Thread.UncaughtExceptionHandler接管,把错误截了不显示。

原来,我们只是把Activity界面结束了,但界面结束后,只要有线程在跑,程序其实仍在运行,可谓马照跑舞照跳。Activity关闭后只是界面消失了,其它该有的东西完全是照常进行;如果线程中有网络请求,则还是照样占用CPU和带宽。

继续研究,发现一个有趣的现象,程序退出后,再次启动程序,发现用public static声明的全局变量居然没变。什么意思呢?举个例子,如果你的MainActivity中有一个全局静态变量public static int c,默认值为0,程序第一次启动你在onCreate里设置它加1,即执行c+=1或c++;然后你关闭程序,马上再次启动程序,这时c的值仍为1,并没有清为0,执行c+=1之后它会变成2;然后你不停地打开关闭程序,就会发现c值在不停地增加。

接着很自然就会再研究Android的Application,因为据说Application在程序中是比较唯一的,适合放置全局变量。我在程序中创建并使用了自己的Application类,然后同样在里面放全局静态变量进行赋值测试,结果照旧——程序关闭再启动时系统并未清除全局变量。

于是我在Application的onCreate中写启动日志(它还有个onTerminate事件,不过实践并看完帮助后才知道那个是假的),结果发现,onCreate其实只在第一次启动时调用,第二次启动时并没有重新创建Application。意思是什么呢?悲哀呀,我们的程序根本就没退出。

原来我们Activity关闭后程序并没有结束,我们的结束程序其实只是演给自己看,本质上程序压根就没退出,程序就一直在后台,除非你用具有ROOT权限的任务管理器结束,否则它永远不会主动退出。

当然了,我以上试验都是在内存充足的情况下进行。程序虽然不会主动退出,但内存清理时系统还是会被退出的。由于谷歌没提供退出的功能,因此很明显,谷歌就是要我们知道,你不必主动退出程序,我会在需要时帮你退出。

对于习惯退出的PC程序员来说,这真是没天理啊,凭啥我退出了你还要占着宝贵的内存?甚至说不定还占着其它资源。我一开始也很不理解,不过后来一想,其实内存占着也无所谓,只要不占CPU,内存平时空着也是浪费的,反正也不耗电,当下一次加载时还能提速,而内存不足时也能自动清理,问题不大吧。不能全退就不全退呗,死不了。

后来又发生了一件事,让我对Android的Activity和内存机制又有不同的看法了。我同事有一台电信送的手机,配置很差,只有几百M内存,在上面跑我的程序,发现一个怪异的现象:我在程序里逐次打开了三个包含编辑框的Activity:A、B和C,并且这三个Activity里都输入了不同的内容,当前显示的是C;然后我按HOME键,打个电话,再用任务管理器切换回程序,这时程序显示的确实是原来的Activity C,但上面编辑框的内容却消失了;再返回到B、A,发现B、A的编辑内容也消失了;也就是说,A、B、C的界面堆栈顺序还在,但界面的状态却丢失了。

世上哪有这么神奇的事,仔细一调试就知道了,原来在按HOME键打完电话回到程序时,程序的Activity的onCreate被再次调用,程序等于是重新创建了Activity C。

继续研究发现,原来不仅仅是Activity C,其它两个Activity A和B也是重新创建了。

继续再研究,发现其实连Application都重新创建了,所有全局变量已经清空。这正是我原来想要的退出效果,在我不需要的时候它出来了,够讽剌的。

至此真相大白,原来在按HOME键打电话时,由于内存不足,系统自动把我的程序结束了,结束前它会记录Activity堆栈,会调用Activity的onSaveInstanceState和Application的onLowMemory让程序有机会保存数据;当再次回到程序时,系统会自动重新创建Application,然后按堆栈顺序先恢复Activity C;但这时A和B可能还没恢复,这就是说,我们平时以为Activity A和B在C后面的假设真的很假,其实并不存在,存在的只是一个堆栈信息;除了顶级Activity,所有界面和全局变量都已经清空。

了解了这些之后,我发现之前做的退出什么的都是浮云了,相反我们搞退出不但没好处还会造成不应有的混乱。这种情况下,我们自己搞堆栈做程序退出真是没有任何意义。

最后我只好投降了,我的程序只搞假退出,再也不管真正退出了。我在ROOT Activity退出时会做个标记,下次进来时会自动重新清理和设置一些全局变量,这就算重启程序了。想真的退出程序?等谷歌的新API看有没退出接口再说吧,目前来说我觉得真的没必要。

顺便说一下程序崩溃,有一段时间我想利用崩溃机制退出程序,最后发现,崩溃机制跟System.exit(0)和android.os.Process.killProcess一样,只能结束当前Activity,同时可能会引起当前或上一个Activity的重新创建触发onCreate事件,但不能清掉整个程序,也只好放弃。


ref:http://blog.csdn.net/huzgd/article/details/7459774

ps:我试了下,android.os.Progress.KillProgress和system.exit(0)发现还是假退出,在类似任务管理器里还是能看到程序在后台,起码小米2是如此的。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 晚上睡觉不安神怎么办 晚上经常睡不着觉怎么办 老是睡不着觉怎么办啊 小孩睡觉不安稳怎么办 睡觉时动不了怎么办 特别累还睡不着怎么办 又累又睡不着怎么办 干活累的睡不着怎么办 狗一有动静就叫怎么办 楼上天天闹动静怎么办 喝了奶茶失眠怎么办 失眠一宿第二天怎么办 睡觉外面噪音大怎么办 怀孕早期晚上睡不着怎么办 短发发尾翘怎么办 很累就是睡不着怎么办 人累但是睡不着怎么办 如果晚上睡不着该怎么办 晚上睡不着觉该怎么办 晚上睡不着该怎么办呢 晚上失眠睡不着该怎么办 晚上一直睡不着该怎么办 怀孕晚上睡不着该怎么办 运动太累睡不着怎么办 运动完睡不着觉怎么办 晚上冷得睡不着怎么办 晚上脚冷睡不着怎么办 短发头发有点乱怎么办 不想让别人睡觉怎么办 15岁晚上睡不着怎么办 16岁青少年失眠怎么办 好累又睡不着怎么办 造口患者拉肚子怎么办? 起床后头发乱怎么办 新生儿睡觉偏头怎么办 婴儿睡觉偏头怎么办 月经期间血下不来怎么办 月经下不来怎么办一点点咖啡色 突然早睡睡不着怎么办 移植后睡不着觉怎么办 孕期喜欢右侧睡怎么办