zoukankan      html  css  js  c++  java
  • Activity声明周期容易出现的问题

    了解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导致的内存泄漏

    注:这篇博文涉及的源码可以在 GitHub 上面下载哦

  • 相关阅读:
    php字符串常用函数
    调试心得总结
    搜索查询简单的网页摘要生成
    OFFICE三线表的制作
    阶段性总结20130613
    url查重bloom过滤器
    Linuxvim常用命令
    不打开文件操作db时,如果遇到和窗体交互,不会提示文档未锁,但同样需要锁定当前文档,代码如下
    样条曲线
    不用遍历得到btr中同一类型的实体 CAD2009 vs2008及以上
  • 原文地址:https://www.cnblogs.com/yizuochengchi2012/p/4657744.html
Copyright © 2011-2022 走看看