Activity声明周期容易出现的问题
2015-07-18 21:36
253 查看
了解activity的生命周期,不仅仅是回答面试官的几个小问题:下面这篇文章不错,截取个人认为优秀的部分分享给大家,欢迎交流.感谢原作者 /** * 示例向我们展示了在 Activity 的配置改变时(配置改变会导致其下的 Activity 实例被销 * 毁)存活。此外,Activity 的 context 也是内存泄漏的一部分,因为每一个线程都被初始 * 化为匿名内部类,使得每一个线程都持有一个外部 Activity 实例的隐式引用,使得 * Activity 不会被 Java 的垃圾回收机制回收。 */ public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); exampleOne(); } private void exampleOne() { new Thread() { @Override public void run() { while (true) { SystemClock.sleep(1000); } } }.start(); } }
Activity 配置发生改变会使 Activity 被销毁,并新建一个 Activity,我们总会觉得 Android 系统会将与被销毁的 Activity 相关的一切清理干净,例如回收与 Activity 关联的内存,Activity 执行的线程等等……然而,现实总是很残酷的,刚刚提到的这些东西都不会被回收,并导致内存泄漏,从而显著地影响应用的性能表现。
Activity 内存泄漏的根源
每一次配置的改变都会使 Android 系统新建一个 Activity 并把改变前的 Activity 交给垃圾回收机制回收。但因为线程持有旧 Activity 的隐式引用,使该 Activity 没有被垃圾回收机制回收。我们把该线程类声明为私有的静态内部类就可以解决这个问题:
/** * 示例通过将线程类声明为私有的静态内部类避免了 Activity context 的内存泄漏问题,但 * 在配置发生改变后,线程仍然会执行。原因在于,DVM 虚拟机持有所有运行线程的引用,无论 * 这些线程是否被回收,都与 Activity 的生命周期无关。运行中的线程只会继续运行,直到 * Android 系统将整个应用进程杀死 */ public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); exampleTwo(); } private void exampleTwo() { new MyThread().start(); } private static class MyThread extends Thread { @Override public void run() { while (true) { SystemClock.sleep(1000); } } } }
通过上面的代码,新线程再也不会持有一个外部 Activity 的隐式引用,而且该 Activity 也会在配置改变后被回收。
下面是一种解决办法:
/** * 除了我们需要实现销毁逻辑以保证线程不会发生内存泄漏,其他代码和示例2相同。在退出当前 * Activity 前使用 onDestroy() 方法结束你的运行中线程是个不错的选择 */ public class MainActivity extends Activity { private MyThread mThread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); exampleThree(); } private void exampleThree() { mThread = new MyThread(); mThread.start(); } /** * 私有的静态内部类不会持有其外部类的引用,使得 Activity 实例不会在配置改变时发生内 * 存泄漏 */ private static class MyThread extends Thread { private boolean mRunning = false; @Override public void run() { mRunning = true; while (mRunning) { SystemClock.sleep(1000); } } public void close() { mRunning = false; } } @Override protected void onDestroy() { super.onDestroy(); mThread.close(); } }
通过上面的代码,我们在 onDestroy() 方法中结束了线程,确保不会发生意外的线程的内存泄漏问题。如果你想要在配置改变后保留该线程(而不是每一次在关闭 Activity 后都要新建一个线程),那我建议你使用 Fragment 去完成该耗时任务。百度一篇叫作“Handling Configuration Changes with Fragments”应该能满足你的需求,在API demo中也提供了很好理解的例子来为你阐述相关概念。
在Activity中使用Thread导致的内存泄漏
原文链接 : Activitys, Threads, & Memory Leaks
原文作者 : AlexLockwood
译文出自 : 开发技术前线 www.devtf.cn
译者 : chaossss
校对者: yinna317
状态 : 完成
注:这篇博文涉及的源码可以在 GitHub 上面下载哦
相关文章推荐
- 每天学习一点新东西——vim篇(二)
- swift2 枚举类型
- log4j:WARN Please initialize the log4j system properly解决办法
- div、css入门练习
- FZU 2184 逆序数还原
- minizlib
- 图解HTTP
- UIScrollView控件实现图片轮播
- top 25 论文
- POJ 2328 Guessing Game
- Linux编程常用头文件汇总
- android com.handmark.pulltorefresh 使用技巧
- 为什么 as sysdba着陆方法oracle数据库,为什么刚刚输入username和password我们都可以登录?
- 设计模式_建造者模式
- codeforces Gym 100187L L. Ministry of Truth 水题
- 【机房重构】最后总结
- POJ 2656 Unhappy Jinjin
- Apache Web Server -> httpd的HTTP的多路处理模块MPM
- lua——基础语法
- Overload、Overwrite和Override