Android上的内存泄漏问题

一、什么是内存泄漏?
  • 无用的对象没有被及时释放引用,导致GC无法回收,就有可能出现内存泄漏。
二、内存泄漏带来的危害是什么?
  • 内存泄漏会增加内存占用和OOM几率。
三、哪些代码的写法会导致内存泄漏?
  • 常见五种导致 APP 内存泄漏的地方
    1. 静态 Activity
      泄漏 activity 最简单的方法就是在 activity 类中定义一个 static 变量,并且将其指向一个运行中的 activity 实例。如果在 activity 的生命周期结束之前,没有清除这个引用,那它就会泄漏了。这是因为 activity(例如 MainActivity) 的类对象是静态的,一旦加载,就会在 APP 运行时一直常驻内存,因此如果类对象不卸载,其静态成员就不会被垃圾回收。
    void setStaticActivity() {
      activity = this;
    }

    View saButton = findViewById(R.id.sa_button);
    saButton.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View v) {
            setStaticActivity();
            nextActivity();
      }
    });
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
 ![这里写图片描述](https://img-blog.csdn.net/20160712180226946)

 
 
  • 1
  • 2

2. 内部类或者匿名内部类
类似的,匿名类同样会持有定义它们的对象的引用。因此如果在 activity 内定义了一个匿名的 AsyncTask 对象,就有可能发生内存泄漏了。如果 activity 被销毁之后 AsyncTask 仍然在执行,那就会组织垃圾回收器回收 activity 对象,进而导致内存泄漏,直到执行结束才能回收 activity。

    void startAsyncTask() {
        new AsyncTask<Void, Void, Void>() {
            @Override protected Void doInBackground(Void... params) {
                while(true);
            }
        }.execute();
    }

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    View aicButton = findViewById(R.id.at_button);
    aicButton.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View v) {
            startAsyncTask();
            nextActivity();
        }
    });
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
 ![这里写图片描述](https://img-blog.csdn.net/20160712181354592)

 
 
  • 1
  • 2

3. Handlers
同样的,定义一个匿名的 Runnable 对象并将其提交到 Handler 上也可能导致 activity 泄漏。Runnable 对象间接地引用了定义它的 activity 对象,而它会被提交到 Handler 的 MessageQueue 中,如果它在 activity 销毁时还没有被处理,那就会导致 activity 泄漏了。

    void createHandler() {
        new Handler() {
            @Override public void handleMessage(Message message) {
                   super.handleMessage(message);
                }
            }.postDelayed(new Runnable() {
                @Override public void run() {
                        while(true);
                }
          }, Long.MAX_VALUE >> 1);
    }

    View hButton = findViewById(R.id.h_button);
    hButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
        createHandler();
        nextActivity();
        }
});
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
 ![这里写图片描述](https://img-blog.csdn.net/20160712183514777)

 
 
  • 1
  • 2

4. EditText
EditText所处的上下文对象会一直保留在(4.0.x,4.1.x,4.2.x)的系统版本中。大家在用着它这么长的时间不知道系统还有这么个bug(具体可参考:https://dddpaul.github.io/blog/2014/08/01/android-memory-leaks/),但好在Android 4.3, API 18的系统版本上修复了该问题,但是对于18以下的就要注意啦,需要做些特殊处理,不然就会导致泄漏的,其实解决办法也是很简单:修改EditText的android:inputType= “textNoSuggestions”
泄露的具体信息如图:
泄露信息

  1. Threads
    同样的,使用 Thread 和 TimerTask 也可能导致 activity 泄漏。
void spawnThread() {
        new Thread() {
            @Override public void run() {
                  while(true);
            }
        }.start();
    }

    View tButton = findViewById(R.id.t_button);
    tButton.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View v) {
          spawnThread();
          nextActivity();
      }
    });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值