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 上面下载哦

  • 相关阅读:
    Linnia学习记录
    漫漫考研路
    ENS的学习记录
    KnockoutJS 3.X API 第四章 数据绑定(4) 控制流with绑定
    KnockoutJS 3.X API 第四章 数据绑定(3) 控制流if绑定和ifnot绑定
    KnockoutJS 3.X API 第四章 数据绑定(2) 控制流foreach绑定
    KnockoutJS 3.X API 第四章 数据绑定(1) 文本及样式绑定
    KnockoutJS 3.X API 第三章 计算监控属性(5) 参考手册
    KnockoutJS 3.X API 第三章 计算监控属性(4)Pure computed observables
    KnockoutJS 3.X API 第三章 计算监控属性(3) KO如何实现依赖追踪
  • 原文地址:https://www.cnblogs.com/yizuochengchi2012/p/4657744.html
Copyright © 2011-2022 走看看