1. 静态 Activity

2. 静态 View

3. 非静态内部类

4. 匿名类

5. Handler

6. Thread

7. TimerTask

8. SensorManager

1.资源对象没关闭造成的内存泄漏

2.构造Adapter时,没有使用缓存的convertView

3.Bitmap对象不在使用时调用recycle()释放内存

4.试着使用关于application的context来替代和activity相关的context

5.注册没取消造成的内存泄漏

6.集合中对象没清理造成的内存泄漏

避免引用Context造成的内存泄露

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

interface 放在fragment内或者放在外面单独存在,一般不会造成activity泄漏
public interface DialogCallback {
void showModifyInputDialog();
void showTheMessageDialog();
} 其实一般的匿名内部类是不会导致activity释放不了的,只要你不在handle内进行奇怪的操作
private Handler uiHandler = new Handler(){

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

内存泄漏全解析

最近在维护代码,发现一个自定义View(这个View是在一个AsyncTask的工作线程doInBackground中新建的,在UI线程onPostExecute中添加进window中的)经常会泄漏内存,导致其引用的Activity一直得不到释放,每次退出再进去都会导致Activity的对象+1.

package com.xxx.launcher.view;

import android.content.Context;
import android.util.Log;
import android.view.View; public class WeatherTextView extends SkinTextView { public WeatherTextView (Context context) {
super(context);
postDelayed(mShowCityRunnable, );//这一步有问题
} @Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
if (visibility == View.VISIBLE) {
post(mShowCityRunnable);
}
} @Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
onCancel();
}; public void onCancel(){
removeCallbacks(mShowCityRunnable);
}
private Runnable mShowCityRunnable = new Runnable() { @Override
public void run() {
Log.i("mShowCityRunnable-------TAG", "run"+mShowCityRunnable);
setText(city);
}
};
}

最后通过MAT工具查看内存快照的比较,发现了如下的情况,把内存泄露的地方锁定在了WeatherTextView$2的第二个内部类中mShowCityRunnable ,一开始始终都想不到这个内部类到底有什么地方泄露了,最后突然灵光一闪,是不是View的post()方法导致的,在网上一查,发现确实。

public boolean post(Runnable action) {
Handler handler;
AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
handler = attachInfo.mHandler;
} else {
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
} return handler.post(action);
}

在post() 函数注释中,明确写着:This method can be invoked from outside of the UI thread only when this View is attached to a window.

当View还没有attach到当前window时,mAttachInfo 值为 null,故而执行 else语句,再看一下getRunQueue()和其post() 方法:

static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<RunQueue>();  

static RunQueue getRunQueue() {
RunQueue rq = sRunQueues.get();
if (rq != null) {
return rq;
}
rq = new RunQueue();
sRunQueues.set(rq);
return rq;
}
……
static final class RunQueue {
private final ArrayList<HandlerAction> mActions = new ArrayList<HandlerAction>(); void post(Runnable action) {
postDelayed(action, );
} void postDelayed(Runnable action, long delayMillis) {
HandlerAction handlerAction = new HandlerAction();
handlerAction.action = action;
handlerAction.delay = delayMillis; synchronized (mActions) {
mActions.add(handlerAction);
}
} void executeActions(Handler handler) {
synchronized (mActions) {
final ArrayList<handleraction> actions = mActions;
final int count = actions.size(); for (int i = ; i < count; i++) {
final HandlerAction handlerAction = actions.get(i);
handler.postDelayed(handlerAction.action, handlerAction.delay);
} actions.clear();
}
}
……
}

这样会把Runnable 插入到一个静态的ThreadLocal的RunQueue队列里(在工作线程中post,就会插入工作线程的RunQueue队列),针对本文开头给出的例子,那么插入的Runnable什么时候得到执行呢?

调用RunQueue.executeActions()方法只有一处,即在ViewRootImpl类的如下非静态方法中

private void performTraversals() {  

        if (mLayoutRequested && !mStopped) {
// Execute enqueued actions on every layout in case a view that was detached
// enqueued an action after being detached
getRunQueue().executeActions(attachInfo.mHandler);
}
}

该方法是在UI线程执行的(见ViewRootImpl.handleMessage()), 故当UI线程执行到该performTraversals() 里的 getRunQueue() 时,得到的是UI线程中的RunQueue,这样AsyncTask 线程中的 RunQueue永远不会被执行到, 并且AsyncTask的是用线程池实现的,AsyncTask启动的线程会长期存在,造成如下引用关系:

AsyncTask线程 => 静态的ThreadLocal的RunQueue => Runnable => View=> Activity;

如此即使activity finish 了,确始终存在一个静态引用链引用这该activity,而 Activity一般又引用着很多资源,比如图片等,最终造成严重资源泄漏。

最后我是写改成

package com.xxx.launcher.view;

import android.content.Context;
import android.util.Log;
import android.view.View; public class WeatherTextView extends SkinTextView { public WeatherTextView (Context context) {
super(context);
} @Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
postDelayed(mShowCityRunnable, ); //在onAttachedToWindow方法中执行post方法
} @Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
if (visibility == View.VISIBLE) {
post(mShowCityRunnable);
}
} @Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
onCancel();
}; public void onCancel(){
removeCallbacks(mShowCityRunnable);
}
private Runnable mShowCityRunnable = new Runnable() { @Override
public void run() {
Log.i("mShowCityRunnable-------TAG", "run"+mShowCityRunnable);
setText(city);
}
};
}

这样Activity就没有再被其他东西引用了,就不会发生Activity的泄漏了,Activity就可以被释放了。这样,不管进入退出进入这个MainMenuActivity多少次,MainMenuActivity的对象就只会保存一份。

ps:至于为什么在两个Histogram(直方图)的比较图中还是显示MainMenuActivity+1,则是因为这是类名,类被加载之后,在进程结束之前不会被回收

===============================================================================================================================

===============================================================================================================================

这种泄漏一般是因为mStorageManager 注册了但是没有取消注册

mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
mStorageManager.registerListener(mStoragelistener);

取消注册就可以了

if (mStorageManager != null) {
mStorageManager.unregisterListener(mStoragelistener);
}

Android 内存泄漏的一些情况。的更多相关文章

  1. android 内存泄漏出现的情况

    非静态内部类的静态实例由于内部类默认持有外部类的引用,而静态实例属于类.所以,当外部类被销毁时,内部类仍然持有外部类的引用,致使外部类无法被GC回收.因此造成内存泄露. 类的静态变量持有大数据对象静态 ...

  2. Android - 内存泄漏的情况以及解决方法

    [译]Android内存泄漏的八种可能(上) Android防止内存泄漏的八种方法(下). Static Activities 在类中定义了静态Activity变量,把当前运行的Activity实例赋 ...

  3. 【转】android 内存泄漏相关收藏博客。

    关于android内存泄漏的研究   博客建了几个月,都没有去写,一是因为当时换工作,然后又是新入职(你懂的,好好表现),比较忙:二是也因为自己没有写博客的习惯了.现在还算是比较稳定了,加上这个迭代基 ...

  4. 关于android内存泄漏的研究

    博客建了几个月,都没有去写,一是因为当时换工作,然后又是新入职(你懂的,好好表现),比较忙:二是也因为自己没有写博客的习惯了.现在还算是比较稳定了,加上这个迭代基本也快结束了,有点时间来写写博客.好了 ...

  5. Android内存泄漏的各种原因详解

    转自:http://mobile.51cto.com/abased-406286.htm 1.资源对象没关闭造成的内存泄漏 描述: 资源性对象比如(Cursor,File文件等)往往都用了一些缓冲,我 ...

  6. Android 内存泄漏优化汇总

    android内存泄漏优化摘要 博客分类: android android内存溢出OutOfMemoryError . android移动应用程序的内存分配一般是8凯瑟琳约,不正确地假定处理内存处理非 ...

  7. Android内存泄漏检测利器:LeakCanary

    Android内存泄漏检测利器:LeakCanary MAR 28TH, 2016 是什么? 一言以蔽之:LeakCanary是一个傻瓜化并且可视化的内存泄露分析工具 为什么需要LeakCanary? ...

  8. Android 内存泄漏分析与解决方法

    在分析Android内存泄漏之前,先了解一下JAVA的一些知识 1. JAVA中的对象的创建 使用new指令生成对象时,堆内存将会为此开辟一份空间存放该对象 垃圾回收器回收非存活的对象,并释放对应的内 ...

  9. [Android]Android内存泄漏你所要知道的一切(翻译)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/7235616.html Android内存泄漏你所要知道的一切 ...

随机推荐

  1. 【微信SEO】公众号也能做排名?

    [写于2016年8月] 最近,微信团队发出一则公告,开放公众号运营者一年内更改公众号名一次,这对不少名字起的奇葩名字(包括dkplus)的公众号来说是一件好事. 为什么说是好事呢?公众号名字直接关联到 ...

  2. 作为前端应当了解的Web缓存知识

    缓存优点 通常所说的Web缓存指的是可以自动保存常见http请求副本的http设备.对于前端开发者来说,浏览器充当了重要角色.除此外常见的还有各种各样的代理服务器也可以做缓存.当Web请求到达缓存时, ...

  3. C# 线程同步的三类情景

    C# 已经提供了我们几种非常好用的类库如 BackgroundWorker.Thread.Task等,借助它们,我们就能够分分钟编写出一个多线程的应用程序. 比如这样一个需求:有一个 Winform ...

  4. Egret 集成第三方库 记录

    引入第三方库pureMVC 这次我们要使用到一个mvc开发框架-pureMVC,熟悉as3的朋友一定也对这个框架不陌生吧.不熟悉的也没关系,这个框架不是这次的主角.我们从 这里 下载pureMVC的T ...

  5. GDB 多线程调试:只停止断点的线程,其他线程任然执行; 或只运行某些线程 其他线程中断

    多线程调试之痛 调试器(如VS2008和老版GDB)往往只支持all-stop模式,调试多线程程序时,如果某个线程断在一个断点上,你的调试器会让整个程序freeze,直到你continue这个线程,程 ...

  6. css的五种属性值----在路上(21)

    在CSS中,每个属性的属性值都有一定的范围,并且不同类型的属性值有不同的值.对于一个属性,必须取得正确的属性值,才能被浏览器正确地解释,因此一定要弄清每种类型的属性值范围.在CSS中属性一般有以下几种 ...

  7. 基于Caffe的Large Margin Softmax Loss的实现(上)

    小喵的唠叨话:在写完上一次的博客之后,已经过去了2个月的时间,小喵在此期间,做了大量的实验工作,最终在使用的DeepID2的方法之后,取得了很不错的结果.这次呢,主要讲述一个比较新的论文中的方法,L- ...

  8. AOP概述

    了解AOP之前,先大概讲述一下SOC: Soc:Separation of concerns 关注分离点, 在不同的场景SOC有着不同的含义 Soc是一个过程:Soc是一个将功能点分解以尽量减小功能交 ...

  9. ASP.NET MVC5+EF6+EasyUI 后台管理系统(54)-工作流设计-所有流程监控

    系列目录 先补充一个平面化登陆页面代码,自己更换喜欢的颜色背景 @using Apps.Common; @{ Layout = null; } <!DOCTYPE html> <ht ...

  10. YYModel 源码解读(二)之NSObject+YYModel.h (5)

    好了,之前的博文中详细的解释了一些辅助的类和辅助的函数,接下来就是使用它们来实现酷炫功能的时候,正所谓磨刀不误砍柴工啊 我们先把总的功能罗列出来 1. json转字典              + ( ...