1. 了解activity的生命周期,不仅仅是回答面试官的几个小问题:下面这篇文章不错,截取个人认为优秀的部分分享给大家,欢迎交流.感谢原作者
  2.  
  3. /**
  4. * 示例向我们展示了在 Activity 的配置改变时(配置改变会导致其下的 Activity 实例被销
  5. * 毁)存活。此外,Activity 的 context 也是内存泄漏的一部分,因为每一个线程都被初始
  6. * 化为匿名内部类,使得每一个线程都持有一个外部 Activity 实例的隐式引用,使得
  7. * Activity 不会被 Java 的垃圾回收机制回收。
  8. */
  9. public class MainActivity extends Activity {
  10.  
  11. @Override
  12. protected void onCreate(Bundle savedInstanceState) {
  13. super.onCreate(savedInstanceState);
  14. exampleOne();
  15. }
  16.  
  17. private void exampleOne() {
  18. new Thread() {
  19. @Override
  20. public void run() {
  21. while (true) {
  22. SystemClock.sleep(1000);
  23. }
  24. }
  25. }.start();
  26. }
  27. }

Activity 配置发生改变会使 Activity 被销毁,并新建一个 Activity,我们总会觉得 Android 系统会将与被销毁的 Activity 相关的一切清理干净,例如回收与 Activity 关联的内存,Activity 执行的线程等等……然而,现实总是很残酷的,刚刚提到的这些东西都不会被回收,并导致内存泄漏,从而显著地影响应用的性能表现。

Activity 内存泄漏的根源

每一次配置的改变都会使 Android 系统新建一个 Activity 并把改变前的 Activity 交给垃圾回收机制回收。但因为线程持有旧 Activity 的隐式引用,使该 Activity 没有被垃圾回收机制回收。

我们把该线程类声明为私有的静态内部类就可以解决这个问题:

  1. /**
  2. * 示例通过将线程类声明为私有的静态内部类避免了 Activity context 的内存泄漏问题,但
  3. * 在配置发生改变后,线程仍然会执行。原因在于,DVM 虚拟机持有所有运行线程的引用,无论
  4. * 这些线程是否被回收,都与 Activity 的生命周期无关。运行中的线程只会继续运行,直到
  5. * Android 系统将整个应用进程杀死
  6. */
  7. public class MainActivity extends Activity {
  8.  
  9. @Override
  10. protected void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12. exampleTwo();
  13. }
  14.  
  15. private void exampleTwo() {
  16. new MyThread().start();
  17. }
  18.  
  19. private static class MyThread extends Thread {
  20. @Override
  21. public void run() {
  22. while (true) {
  23. SystemClock.sleep(1000);
  24. }
  25. }
  26. }
  27. }

通过上面的代码,新线程再也不会持有一个外部 Activity 的隐式引用,而且该 Activity 也会在配置改变后被回收。

下面是一种解决办法:

  1. /**
  2. * 除了我们需要实现销毁逻辑以保证线程不会发生内存泄漏,其他代码和示例2相同。在退出当前
  3. * Activity 前使用 onDestroy() 方法结束你的运行中线程是个不错的选择
  4. */
  5. public class MainActivity extends Activity {
  6. private MyThread mThread;
  7.  
  8. @Override
  9. protected void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. exampleThree();
  12. }
  13.  
  14. private void exampleThree() {
  15. mThread = new MyThread();
  16. mThread.start();
  17. }
  18.  
  19. /**
  20. * 私有的静态内部类不会持有其外部类的引用,使得 Activity 实例不会在配置改变时发生内
  21. * 存泄漏
  22. */
  23. private static class MyThread extends Thread {
  24. private boolean mRunning = false;
  25.  
  26. @Override
  27. public void run() {
  28. mRunning = true;
  29. while (mRunning) {
  30. SystemClock.sleep(1000);
  31. }
  32. }
  33.  
  34. public void close() {
  35. mRunning = false;
  36. }
  37. }
  38.  
  39. @Override
  40. protected void onDestroy() {
  41. super.onDestroy();
  42. mThread.close();
  43. }
  44. }

通过上面的代码,我们在 onDestroy() 方法中结束了线程,确保不会发生意外的线程的内存泄漏问题。如果你想要在配置改变后保留该线程(而不是每一次在关闭 Activity 后都要新建一个线程),那我建议你使用 Fragment 去完成该耗时任务。百度一篇叫作“Handling Configuration Changes with Fragments”应该能满足你的需求,在API demo中也提供了很好理解的例子来为你阐述相关概念。

在Activity中使用Thread导致的内存泄漏

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

Activity声明周期容易出现的问题的更多相关文章

  1. android activity声明周期学习笔记

    android生命周期图: Activity继承了ApplicationContext: 1:初次加载activity时顺序执行:onCreate()-->onStart()-->onRe ...

  2. Activity声明周期2

    FirstActivity.java import android.os.Bundle; import android.view.View; import android.view.View.OnCl ...

  3. Activity声明周期1

    oncreate():在Activity对象第一次创建时调用 onStart():当Activity变得可见时调用该函数 onResume():当Activity开始准备于用户交互时调用该方法(即获得 ...

  4. xamarin Android activity生命周期详解

    学Xamarin我为什么要写这样一篇关于Android 的activity生命周期的文章 已经学Xamarin android有一段时间了,现在想起当初Xamarin也走了不少的弯路.当然Xamari ...

  5. Android学习路线(十二)Activity生命周期——启动一个Activity

    DEMO下载地址:http://download.csdn.net/detail/sweetvvck/7728735 不像其他的编程模式那样应用是通过main()函数启动的.Android系统通过调用 ...

  6. activity和fragment的声明周期

    Activity生命周期: Fragment生命周期:

  7. android开发------Activity生命周期

    这几天工作比较忙,基本没有什么时间更新播客了. 趁着今晚有点时间,我们来简单说一下什么是Activity生命周期和它们各阶段的特征 什么是生命周期 在还没有接触android开发的时候,听到有人说Ac ...

  8. Android-管理Activity生命周期 -开始一个Activity

    很多程序都是从main()方法开始启动的,和其他程序不同,android是在activity生命周期的特定状态的特定回调方法中初始化代码的.activity启动和销毁的时候都用很多回调方法. 这里将要 ...

  9. Activity生命周期解决(有图有真相)

    Activity完整的生命周期: 启动Activity的周期历程: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcGVuZ2t2/font/5a6L5L2 ...

随机推荐

  1. CodeSmith中SchemaExplorer属性的介绍

    CodeSmith与数据库的联系,在CodeSmith中自带一个程序集SchemaExplorer.dll,这个程序集中的类主要用于获取数据库中各种对象的结构. <%@ Property Nam ...

  2. 一步一步建MVC

    http://www.cnblogs.com/yuangang/p/5569518.html

  3. c语言_链表实例讲解(两个经典例子)

    建立一个学生成绩的线性链表,对其实现插入,删除,输出,最后销毁. demo1 // lianbiao.cpp : Defines the entry point for the console app ...

  4. WIN7 64位配置Oracle SQL Developer工具

    在使用Oracle SQL 的过程中,很多参考资料,辅导机构,各种书籍绝大多数都是使用PL/SQL进行讲解,但是问题是PL/SQL对WIN7 64位系统支持不好,网上有各种各样的配置教程,我尝试了很多 ...

  5. js原型解析

    我们都知道javascript因为具有了继承以及变量等等一系列的特性之后才被人们认为具有一门编程语言的资格,在后续的不断发展中,js在原生的基础上扩展了基于jquery等等的库,甚至衍生了像node. ...

  6. 使用Ubuntu 新建vpn过程

    1.更新软件源      sudo apt-get update   2.安装pip    sudo apt-get install python-pip   3.安装shadowsocks    s ...

  7. ZOJ 1074 To the Max(DP 最大子矩阵和)

    To the Max Time Limit: 2 Seconds      Memory Limit: 65536 KB Problem Given a two-dimensional array o ...

  8. Net常用资源小集

    Visual Studio——IDEs工具之王,.NET开发者的必备IDE.Visual Studio提供非常强大的启动工具箱,并且还有一些让人惊喜的插件支持.在去年,微软发布了Visual Stud ...

  9. 对N个数组进行操作。先把这N个一维数组合并成一个2为数组;然后进行操作

    using System;using System.Collections.Generic;using System.Linq;using System.Collections;using Syste ...

  10. 转 C#开发微信门户及应用(1)--开始使用微信接口

    微信应用如火如荼,很多公司都希望搭上信息快车,这个是一个商机,也是一个技术的方向,因此,有空研究下.学习下微信的相关开发,也就成为日常计划的重要事情之一了.本系列文章希望从一个循序渐进的角度上,全面介 ...