`
long_yu2
  • 浏览: 337255 次
社区版块
存档分类
最新评论

你真的有必要退出吗——再说Android程序的退出功能

阅读更多
搞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事件,但不能清掉整个程序,也只好放弃。
分享到:
评论

相关推荐

    android——退出程序的功能,关闭所有本程序界面

    在Android开发中,退出应用程序的功能通常涉及到关闭所有与之相关的活动(Activities)并清理资源。在Android系统中,一个应用程序实际上是由多个Activity组成的,每个Activity代表一个用户界面。当用户在应用之间...

    安卓Android源码——完全退出程序的方法.rar

    本资料“安卓Android源码——完全退出程序的方法.rar”可能包含了一些实现这一功能的具体代码示例。下面将详细讨论如何在Android应用中实现完全退出。 首先,了解Android应用生命周期是至关重要的。一个Android应用...

    安卓Android源码——完全退出程序的方法.zip

    本压缩包文件“安卓Android源码——完全退出程序的方法.zip”可能包含了一个示例代码,展示了如何实现这一功能。下面我们将详细探讨在Android中完全退出程序的方法。 首先,理解Android的应用程序生命周期至关重要...

    安卓Android源码——返回键退出程序的两种方式.rar

    在安卓(Android)开发中,实现应用程序通过返回键(back key)退出是一个常见的需求。本压缩包中的资源可能包含了两种不同的方法来实现这一功能。以下是关于这个主题的详细讲解: 一、第一种方式:重写Activity的...

    安卓Android源码——返回键退出程序的两种方式.zip

    在安卓(Android)系统中,开发应用程序时,处理返回键以退出程序是常见的需求。本文将深入探讨两种主要的方法,帮助开发者理解并实现这一功能。 首先,我们要知道,Android应用程序通常由多个活动(Activity)组成...

    安卓Android源码——安卓Android 文件操作 列表显示 进入 退出 删除 复制 粘贴 新建文件等等.zip

    本资源"安卓Android源码——安卓Android 文件操作 列表显示 进入 退出 删除 复制 粘贴 新建文件等等.zip"提供了相关的源码示例,帮助开发者理解和实现这些功能。下面我们将详细探讨这些知识点: 1. **文件操作**: ...

    安卓Android源码——安卓Android 文件操作 列表显示 进入 退出 删除 复制 粘贴 新建文件等等.rar

    这份“安卓Android源码——安卓Android 文件操作 列表显示 进入 退出 删除 复制 粘贴 新建文件等等.rar”资源提供了实现这些功能的源代码示例。下面,我们将详细探讨这些关键知识点。 1. 文件操作: 在Android中,...

    动手学Android之十三——动起来例子程序

    "动手学Android之十三——动起来例子程序"是一个专门针对Android动画的学习资源,旨在帮助开发者全面理解并掌握Android平台上的动画技术。这个程序实例涵盖了Android动画的各个方面,从基本的平移动画、旋转动画到更...

    Android程序开发——音乐播放器

    ### Android程序开发——音乐播放器知识点详述 #### 一、系统简介 ##### 1.1 功能概述 - **音乐播放**: 支持播放存储于SD卡中的MP3格式音乐。 - **铃声设置**: 可以将音乐设置为来电铃声、闹铃铃声或通知铃声。 - *...

    安卓Android源码——安卓Android学习——数据存储.rar

    在安卓(Android)系统中,数据存储是应用开发不可或缺的一部分,它允许应用程序持久化数据,以便在用户退出或设备重启后仍然能够访问。本压缩包文件"安卓Android源码——安卓Android学习——数据存储.rar"显然是...

    安卓Android源码——安卓Android实现Windows风格的Dialog.zip

    这个资源包"安卓Android源码——安卓Android实现Windows风格的Dialog.rar"很可能包含了实现这一功能的完整源代码,包括布局文件、自定义Dialog类和可能的样例用法。研究这些源码可以帮助开发者深入理解如何在Android...

    安卓Android源码——闪屏加退出提示.rar

    在安卓(Android)开发中,"安卓Android源码——闪屏加退出提示.rar"这个压缩包文件包含了两个关键功能的实现源代码:闪屏页(Splash Screen)和应用退出提示。闪屏页通常用于应用程序启动时展示品牌形象或加载初始...

    安卓Android源码——闪屏加退出提示应用.zip

    本压缩包"安卓Android源码——闪屏加退出提示应用.zip"可能包含了实现这两个功能的具体代码示例。 1. **闪屏页(Splash Screen)**: 闪屏页通常是在应用程序启动时首先展示的页面,它一般用来显示品牌标识、加载...

    安卓Android源码——安卓Android中实现Iphone样式的AlertDialog.rar

    "安卓Android源码——安卓Android中实现Iphone样式的AlertDialog.rar"这个压缩包文件提供了一个示例,教你如何在Android应用中模仿iPhone样式的AlertDialog,使得用户界面更加接近iOS的体验。 在Android开发中,...

    安卓Android源码——Android 英语单词记忆程序源码.zip

    在本项目中,我们主要探讨的是一个基于Android平台的英语单词记忆程序的源代码。这个程序旨在帮助用户高效地学习和记忆英语单词,利用Android系统的特性来提供互动式的学习体验。下面将详细介绍这个项目的相关知识点...

    安卓Android源码——闪屏加退出提示.zip

    在安卓(Android)应用开发中,为用户提供良好的用户体验至关重要,其中闪屏页(Splash Screen)和退出提示是常见的两种设计模式。闪屏页通常用于展示品牌形象、加载应用程序资源,而退出提示则是为了防止用户意外...

    Android源码——Gps日志记录程序源码.7z

    这个压缩包“Android源码——Gps日志记录程序源码.7z”包含了一个Android应用程序的源代码,该程序专门用于记录和管理GPS日志。通过分析这个源码,我们可以深入理解Android如何与GPS硬件交互以及如何处理定位数据。 ...

Global site tag (gtag.js) - Google Analytics