当前位置:首页 » 安卓系统 » android内存泄露解决

android内存泄露解决

发布时间: 2022-06-01 03:09:17

❶ Android中如何查找内存泄露

1、首先确定是否有内存泄露及哪个程序造成。
1.1、内存泄露已弹出out of memory对话框的情况。
这种情况很简单,直接看对话框就知道是哪个应用的问题了。然后再分析该应用是否是因为内存泄露造成的
out of memory对话框。
》中介绍的各种方法进行分析,确定是否有内存泄露以及是哪个进程造成的内存泄露。
2、生成hprof文件,用MAT进行分析。
生成hprof文件可以在DDMS选中进程点击窗口左上角的mp hprof file按钮来直接生成,也可以通过在程序加代码中来生成代码2:voidgenerateHprof(){String packageName=getApplicationInfo().packageName;
StringhpFilePath=/data/data/+packageName+/input.hprof;try{//Debug.mpHprofData(/sdcard/input.hprof);Debug.
mpHprofData
(hpFilePath);}catch(IOException e) {//TODOAuto-generated catch block
e.printStackTrace();}}建议使用代码生成hprof,然后使用《
Android内存泄露利器(hprof篇)》中的工具自动提取多个hprof文件,然后用MAT进行比较分析。在MAT导入.hprof文件以后,
MAT会自动解析并生成报告,点击
Dominator Tree
,并按Package分组,选择自己所定义的Package类,比较各个类在不同时期的RetainedHeap
,找出可疑类,然后选择该类,点右键,选中
show retained Set项,参看Retained Heap
的详细信息,进一步找出嫌疑项。
3、在代码中查找内存泄露。
根据在MAT找到的内存泄露信息,参照《
Android内存泄漏简介
》进一步在内存中查找内存泄露的原因并解决。
另外如果代码很简单,可以直接参照《
Android内存泄漏简介
》在内存中查找内存泄露的原因并解决。

❷ android内存泄露怎样解决

在Eclipse中新建一个Android工程,名字叫做:memoryleak。功能很简单,只有一个MainActivity和一个ImageUtil。我们在MainActivity中使用ImageUtil来加载图片。注意我们的ImageUtil是单例类。在创建的时候需要传入context。

应用起来以后,转屏。转屏以后,MainActivity会重建,导致ImageUtil重新加载图片。很不幸的是,因为ImageUtil并没有重建,还持有之前的Context,也就是之前的那个MainActivity实例。多次转屏以后,我们在Eclipse的DDMS里面,导出内存映像文件。导出的文件叫做:com.example.memoryleak.hprof。

DDMS导出的内存映像文件并不能被MAT直接使用。需要转换一下。在命令行输入:hprof-conv com.example.memoryleak.hprof memoryleak.hprof。

用MAT打开memoryleak.hprof。

点击“Histogram”
步骤阅读
在Class Name后面的输入框输入应用的名字:com.example.memoryleak。

可以看到有4个MainActivity实例,如果没有泄露的情况下只应该有一个实例,说明存在内存泄露。在MainActivity上点击右键->"Merge
Shortest Paths To GC Roots"->"exclude all phantom/weak/soft
etc.refrences"。

8
在打开的页面中,点击可以看到详细的引用信息。

9
上图中可以看出来是ImageUtil引用了一个MainActivity的实例。这样就找到了泄露的根源,就可以进行处理了。

❸ android内存泄露怎么解决

从谷歌的Android 5.0.1系统开始,就有用户反应存在内存泄漏问题,而在最新版本的Android 5.1更新来看,谷歌似乎并没有解决这个问题,这让许多用户感到非常不满。不过现在从谷歌的AOSP网站来看,似乎已经计划着手解决这个问题,预计会在下次Android 5.1.1更新时到来。 最近包括许多用户反映Android 5.1上Google+等应用会自动重启,某些应用在使用时还会自动退出,导致内存占用率大幅上升,大约会占用750MB到800MB左右。还有用户称打开应用后内存占用率会上升,但关掉应用后系统却不会空出多余内存。而目前许多Nexus 5用户都表示遇到了这个问题。 看来,现在遇到内存泄漏问题的用户还需要再耐性等待一段时间,等到谷歌发布Android 5.1.1更新才行了。

❹ androidstudio内存泄露怎么办

Android studio是没有自带这个工具的,不能分析内存泄露。需要用已经ROOT过的真机来获取APP运行过程中的内存信息,这需要获取该手机的最高权限。如果没有这样的手机,或者没有相应的机型,可以去testbird上面试试云手机吧,上面的手机都是开放最高权限的,而且机型很全。

❺ Android中如何防止内存溢出(摘)

但是Android采用的是java语言编写,所以在很大程度上,Android的内存机制等同于Java的内存机制,在刚开始开发的时候,内存的限制问题会给我们带来内存溢出等严重问题。在我们不使用一些内存的时候,我们要尽量在Android或者其他平台上避免在运行其他程序时,保存必要的状态,使得一些死进程所带来的内存问题,应该尽量在关闭程序或者保存状态的时候释放掉,这样能提高系统在运行方面的流畅性。Android的内存主要表现在:1. 在Android平台上,长期保持一些资源的引用,造成一些内存不能释放,带来的内存泄露问题很多。比如:Context(下文中提到的Activity都是Context),在一些你需要保持你的首个类对象状态,并且把状态传入其他类对象中时,这样消除掉首个类对象之前,你必须先把接收类对象释放掉。需要注意一点的是:因为在Java或者Android内存机制中,顶点的结点释放前必须保证其他对象没有调用才能被系统GC回收释放。我们来看一段代码: @Override protected void onCreate(Bundle state) { super.onCreate(state); TextViewlabel = new TextView(this); label.setText("Leaksare bad"); setContentView(label); }这个代码的意思就是我们把一个TextView的实例加载到了我们正在运行的Activity(Context)当中,因此,通过GC回收机制,我们知道,要释放Context,就必须先释放掉引用他的一些对象。如果没有,那在要释放Context的时候,你会发现会有大量的内存溢出。所以在你不小心的情况下内存溢出是一件非常容易的事情。 保存一些对象时,同时也会造成内存泄露。最简单的比如说位图(Bitmap),比如说:在屏幕旋转时,会破坏当前保持的一个Activity状态,并且重新申请生成新的Activity,直到新的Activity状态被保存。我们再看一段代码: privatestatic Drawable sBackground; @Override protected void onCreate(Bundle state) { super.onCreate(state); TextView label = new TextView(this); label.setText("Leaks are bad"); if (sBackground == null) { sBackground =getDrawable(R.drawable.large_bitmap); } label.setBackgroundDrawable(sBackground); setContentView(label); } 这个代码是非常快的同时也是错误的。它的内存泄露很容易出在屏幕转移的方向上。虽然我们会发现没有显示的保存Context这个实例,但是当我们把绘制的图连接到一个视图的时候,Drawable就会将被View设置为回调,这就说明,在上述的代码中,其实在绘制TextView到活动中的时候,我们已经引用到了这个Activity。链接情况可以表现为:Drawable->TextView->Context。所以在想要释放Context的时候,其实还是保存在内存中,并没有得到释放。如何避免这种情况:主要在于。线程最容易出错。大家不要小看线程,在Android里面线程最容易造成内存泄露。线程产生内存泄露的主要原因在于线程生命周期的不可控。下面有一段代码:publicclass MyTest extends Activity { @Override publicvoid onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); new MyThread().start(); } privateclass MyThread extends Thread{ @Override public void run() { super.run(); //do somthing } } } 代码很简单,但是在Android上又来新问题了,当我们在切换视图屏幕的时候(横竖屏),就会重新建立横屏或者竖屏的Activity。我们形象的认为之前建立的Activity会被回收,但是事实如何呢?Java机制不会给你同样的感受,在我们释放Activity之前,因为run函数没有结束,这样MyThread并没有销毁,因此引用它的Activity(Mytest)也有没有被销毁,因此也带来的内存泄露问题。有些人喜欢用Android提供的AsyncTask,但事实上AsyncTask的问题更加严重,Thread只有在run函数不结束时才出现这种内存泄露问题,然而AsyncTask内部的实现机制是运用了ThreadPoolExcutor,该类产生的Thread对象的生命周期是不确定的,是应用程序无法控制的,因此如果AsyncTask作为Activity的内部类,就更容易出现内存泄露的问题。线程问题的改进方式主要有:(1) 将线程的内部类,改为静态内部类。(2) 在程序中尽量采用弱引用保存Context。 2. BitmapBitmap是一个很万恶的对象,对于一个内存对象,如果该对象所占内存过大,在超出了系统的内存限制时候,内存泄露问题就很明显了。。解决bitmap主要是要解决在内存尽量不保存它或者使得采样率变小。在很多场合下,因为我们的图片像素很高,而对于手机屏幕尺寸来说我们并不用那么高像素比例的图片来加载时,我们就可以先把图片的采样率降低在做原来的UI操作。如果在我们不需要保存bitmap对象的引用时候,我们还可以用软引用来做替换。具体的实例代码google上面也有很多。综上所述,要避免内存泄露,主要要遵循以下几点:第一:不要为Context长期保存引用(要引用Context就要使得引用对象和它本身的生命周期保持一致)。第二:如果要使用到Context,尽量使用ApplicationContext去代替Context,因为ApplicationContext的生命周期较长,引用情况下不会造成内存泄露问题。第三:在你不控制对象的生命周期的情况下避免在你的Activity中使用static变量。尽量使用WeakReference去代替一个static。 A obj = new A(); WeakReference wr = new WeakReference(obj); obj = null; 这是一个简单的弱引用的例子,简单来说就是回收那些NULL值对象所占的内存空间。 java与C系列语言不同之一就是内存操作都是由后台进行的,其中System.gc()方法可以回收内存。 比如你使用了一个BITMAP,在使用之后马上让它的值为NULL,这个BITMAP用过的内存就会被gc回收(也可以直接加上System.gc()快速回收),从而达到利用弱引用来缓解内存溢出的目的。 )第四:垃圾回收器并不保证能准确回收内存,这样在使用自己需要的内容时,主要生命周期和及时释放掉不需要的对象。尽量在Activity的生命周期结束时,在onDestroy中把我们做引用的其他对象做释放,比如:cursor.close()。 其实我们可以在很多方面使用更少的代码去完成程序。比如:我们可以多的使用9patch图片等。有很多细节地方都可以值得我们去发现、挖掘更多的内存问题。

❻ 导致android内存泄漏原因有哪些

Android应用内存泄漏的的原因有以下几个:
1查询数据库后没有关闭游标cursor
2 构造Adapter时,没有使用 convertView 重用
3 Bitmap对象不在使用时调用recycle()释放内存
4 对象被生命周期长的对象引用,如activity被静态集合引用导致activity不能释放

内存泄漏的发现:
通过DDMS中的heap工具,去发现是否有内存溢出。

内存泄漏如何解决:
通过内存分析工具 MAT(Memory Analyzer Tool),找到内存泄露的对象

❼ android scrollview内存溢出怎么解决

android scrollview内存溢出通常是由内存泄露导致。
1、内存泄露导致
由于我们程序的失误,长期保持某些资源(如Context)的引用,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造成内存泄露。
Android 中常见就是Activity被引用在调用finish之后却没有释放,第二次打开activity又重新创建,这样的内存泄露不断的发生,则会导致内存的溢出。
Android的每个应用程序都会使用一个专有的Dalvik虚拟机实例来运行,它是由Zygote服务进程孵化出来的,也就是说每个应用程序都是在属于自己的进程中运行的。Android为不同类型的进程分配了不同的内存使用上限,如果程序在运行过程中出现了内存泄漏的而造成应用进程使用的内存超过了这个上限,则会被系统视为内存泄漏,从而被kill掉,这使得仅仅自己的进程被kill掉,而不会影响其他进程.
2、占用内存较多的对象
保存了多个耗用内存过大的对象(如Bitmap)或加载单个超大的图片,造成内存超出限制。
使用方法比较简单:
· 选择DDMS视图,并打开Devices视图和Heap视图
· 点击选择要监控的进程,比如:上图中我选择的是system_process
· 选中Devices视图界面上的"update heap" 图标
· 点击Heap视图中的"Cause GC" 按钮(相当于向虚拟机发送了一次GC请求的操作)
在Heap视图中选择想要监控的Type,一般我们会观察dataobject的 total size的变化,正常情况下total size的值会稳定在一个有限的范围内,也就说程序中的代码良好,没有造成程序中的对象不被回收的情况。如果代码中存在没有释放对象引用的情况,那么data object的total size在每次GC之后都不会有明显的回落,随着操作次数的增加而total size也在不断的增加。(说明:选择好data object后,不断的操作应用,这样才可以看出total size的变化)。如果totalsize确实是在不断增加而没有回落,说明程序中有没有被释放的资源引用。那么我们应该怎么来定位呢?
Android中内存泄露定位
通过DDMS工具可以判断应用程序中是否存在内存泄漏的问题,那又如何定位到具体出现问题的代码片段,最终找到问题所在呢?内存分析工具MAT Memory Analyzer Tool解决了这一难题。MAT工具是一个Eclipse 插件,同时也有单独的RCP 客户端,MAT工具的解析文件是.hprof,这个文件存放了某进程的内存快照。MAT工具定位内存泄漏具体位置的方法如下:
① 生成.hprof文件。Eclipse中生成.hprof文件的方法有很多,不同Android版本中生成.hprof的方式也稍有差别,但它们整体思路是一样的。我们在DDMS界面选中想要分析的应用进程,在Devices视图界面上方的一行图标按钮中,同时选中“Update Heap”和“Dump HPROF file”两个按钮,这时DDMS将会自动生成当前选中进程的.hprof文件。
② 将.hprof 文件导入到MAT工具中,MAT工具会自动解析并生成报告,点击“Dominator Tree”按钮,并按包分组,选择已定义的包类点右键,在弹出的菜单中选择List objects﹥With incoming references,这时会列出所有可疑的类。右键点击某一项,并选择Path to GC Roots﹥excludeweak/soft references,MAT工具会进一步筛选出跟程序相关的所有内存泄漏的类。这样就可以追踪到某一个产生内存泄漏的类的具体代码中。
使用MAT内存分析工具查找内存泄漏的根本思路是找到哪个类的对象的引用没有被释放,然后分析没有被释放的原因,最终定位到代码中哪些片段存在着内存泄漏。

❽ 9,android内存泄露发生的场景有哪些有什么对应的解决方案

1.查询数据库而没有关闭Cursor
在Android中,Cursor是很常用的一个对象,但在写代码是,经常会有人忘记调用close, 或者因为代码逻辑问题状况导致close未被调用。

通常,在Activity中,我们可以调用startManagingCursor或直接使用managedQuery让Activity自动管理Cursor对象。
但需要注意的是,当Activity介绍后,Cursor将不再可用!
若操作Cursor的代码和UI不同步(如后台线程),那没需要先判断Activity是否已经结束,或者在调用OnDestroy前,先等待后台线程结束。

除此之外,以下也是比较常见的Cursor不会被关闭的情况:

1.try {
2. Cursor c = queryCursor();
3. int a = c.getInt(1);
4. ......
5. c.close();
6.} catch (Exception e) {
7.}
虽然表面看起来,Cursor.close()已经被调用,但若出现异常,将会跳过close(),从而导致内存泄露。
所以,我们的代码应该以如下的方式编写:

01.Cursor c = queryCursor();
02.try {
03. int a = c.getInt(1);
04. ......
05.} catch (Exception e) {
06.} finally {
07. c.close(); //在finally中调用close(), 保证其一定会被调用
08.}

2.调用registerReceiver后未调用unregisterReceiver().
在调用registerReceiver后,若未调用unregisterReceiver,其所占的内存是相当大的。
而我们经常可以看到类似于如下的代码:

01.registerReceiver(new BroadcastReceiver() {
02. ...
03.}, filter); ...
这是个很严重的错误,因为它会导致BroadcastReceiver不会被unregister而导致内存泄露。

3.未关闭InputStream/OutputStream

在使用文件或者访问网络资源时,使用了InputStream/OutputStream也会导致内存泄露

4.Bitmap使用后未调用recycle()
根据SDK的描述,调用recycle并不是必须的。但在实际使用时,Bitmap占用的内存是很大的,所以当我们不再使用时,尽量调用recycle()以释放资源。

5.Context泄露

这是一个很隐晦的内存泄露的情况。
先让我们看一下以下代码:
01.private static Drawable sBackground;
02.
03.@Override
04.protected void onCreate(Bundle state) {
05. super.onCreate(state);
06.
07. TextView label = new TextView(this);
08. label.setText("Leaks are bad");
09.
10. if (sBackground == null) {
11. sBackground = getDrawable(R.drawable.large_bitmap);
12. }
13. label.setBackgroundDrawable(sBackground);
14.
15. setContentView(label);
16.}
在这段代码中,我们使用了一个static的Drawable对象。
这通常发生在我们需要经常调用一个Drawable,而其加载又比较耗时,不希望每次加载Activity都去创建这个Drawable的情况。
此时,使用static无疑是最快的代码编写方式,但是其也非常的糟糕。
当一个Drawable被附加到View时,这个View会被设置为这个Drawable的callback (通过调用Drawable.setCallback()实现)。
这就意味着,这个Drawable拥有一个TextView的引用,而TextView又拥有一个Activity的引用。
这就会导致Activity在销毁后,内存不会被释放。

❾ android开发什么叫内存泄露

下面图片是解决内存泄露的例子。例子来自android学习手册,android学习手册,里面有源码。android学习手册包含9个章节,108个例子,源码文档随便看,例子都是可交互,可运行,源码采用android studio目录结构,高亮显示代码,文档都采用文档结构图显示,可以快速定位。360手机助手中下载,图标上有贝壳

在android程序开发中,当一个对象已经不需要再使用了,本该被回收时,而另外一个正在使用的对象持有它的引用从而导致它不能被回收,这就导致本该被回收的对象不能被回收而停留在堆内存中,内存泄漏就产生了。

内存泄漏有什么影响呢?它是造成应用程序OOM的主要原因之一。由于android系统为每个应用程序分配的内存有限,当一个应用中产生的内存泄漏比较多时,就难免会导致应用所需要的内存超过这个系统分配的内存限额,这就造成了内存溢出而导致应用Crash。

了解了内存泄漏的原因及影响后,我们需要做的就是掌握常见的内存泄漏,并在以后的android程序开发中,尽量避免它。下面小编搜罗了5个android开发中比较常见的内存泄漏问题及解决办法,分享给大家,一起来看看吧。

一、单例造成的内存泄漏

Android的单例模式非常受开发者的喜爱,不过使用的不恰当的话也会造成内存泄漏。因为单例的静态特性使得单例的生命周期和应用的生命周期一样长,这就说明了如果一个对象已经不需要使用了,而单例对象还持有该对象的引用,那么这个对象将不能被正常回收,这就导致了内存泄漏。

如下这个典例:

public class AppManager {

private static AppManager instance;

private Context context;

private AppManager(Context context) {

this.context = context;

}

public static AppManager getInstance(Context context) {

if (instance != null) {

instance = new AppManager(context);

}

return instance;

}

}

这是一个普通的单例模式,当创建这个单例的时候,由于需要传入一个Context,所以这个Context的生命周期的长短至关重要:

1、传入的是Application的Context:这将没有任何问题,因为单例的生命周期和Application的一样长 ;

2、传入的是Activity的Context:当这个Context所对应的Activity退出时,由于该Context和Activity的生命周期一样长(Activity间接继承于Context),所以当前Activity退出时它的内存并不会被回收,因为单例对象持有该Activity的引用。

所以正确的单例应该修改为下面这种方式:

public class AppManager {

private static AppManager instance;

private Context context;

private AppManager(Context context) {

this.context = context.getApplicationContext();

}

public static AppManager getInstance(Context context) {

if (instance != null) {

instance = new AppManager(context);

}

return instance;

}

}

这样不管传入什么Context最终将使用Application的Context,而单例的生命周期和应用的一样长,这样就防止了内存泄漏。

二、非静态内部类创建静态实例造成的内存泄漏

有的时候我们可能会在启动频繁的Activity中,为了避免重复创建相同的数据资源,会出现这种写法:

public class MainActivity extends AppCompatActivity {

private static TestResource mResource = null;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

if(mManager == null){

mManager = new TestResource();

}

//...

}

class TestResource {

//...

}

}

这样就在Activity内部创建了一个非静态内部类的单例,每次启动Activity时都会使用该单例的数据,这样虽然避免了资源的重复创建,不过这种写法却会造成内存泄漏,因为非静态内部类默认会持有外部类的引用,而又使用了该非静态内部类创建了一个静态的实例,该实例的生命周期和应用的一样长,这就导致了该静态实例一直会持有该Activity的引用,导致Activity的内存资源不能正常回收。正确的做法为:

将该内部类设为静态内部类或将该内部类抽取出来封装成一个单例,如果需要使用Context,请使用ApplicationContext 。

三、Handler造成的内存泄漏

Handler的使用造成的内存泄漏问题应该说最为常见了,平时在处理网络任务或者封装一些请求回调等api都应该会借助Handler来处理,对于Handler的使用代码编写一不规范即有可能造成内存泄漏,如下示例:

public class MainActivity extends AppCompatActivity {

private Handler mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

//...

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

loadData();

}

private void loadData(){

//...request

Message message = Message.obtain();

mHandler.sendMessage(message);

}

}

这种创建Handler的方式会造成内存泄漏,由于mHandler是Handler的非静态匿名内部类的实例,所以它持有外部类Activity的引用,我们知道消息队列是在一个Looper线程中不断轮询处理消息,那么当这个Activity退出时消息队列中还有未处理的消息或者正在处理消息,而消息队列中的Message持有mHandler实例的引用,mHandler又持有Activity的引用,所以导致该Activity的内存资源无法及时回收,引发内存泄漏,所以另外一种做法为:

public class MainActivity extends AppCompatActivity {

private MyHandler mHandler = new MyHandler(this);

private TextView mTextView ;

private static class MyHandler extends Handler {

private WeakReference<Context> reference;

public MyHandler(Context context) {

reference = new WeakReference<>(context);

}

@Override

public void handleMessage(Message msg) {

MainActivity activity = (MainActivity) reference.get();

if(activity != null){

activity.mTextView.setText("");

}

}

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTextView = (TextView)findViewById(R.id.textview);

loadData();

}

private void loadData() {

//...request

Message message = Message.obtain();

mHandler.sendMessage(message);

}

}

创建一个静态Handler内部类,然后对Handler持有的对象使用弱引用,这样在回收时也可以回收Handler持有的对象,这样虽然避免了Activity泄漏,不过Looper线程的消息队列中还是可能会有待处理的消息,所以我们在Activity的Destroy时或者Stop时应该移除消息队列中的消息,更准确的做法如下:

public class MainActivity extends AppCompatActivity {

private MyHandler mHandler = new MyHandler(this);

private TextView mTextView ;

private static class MyHandler extends Handler {

private WeakReference<Context> reference;

public MyHandler(Context context) {

reference = new WeakReference<>(context);

}

@Override

public void handleMessage(Message msg) {

MainActivity activity = (MainActivity) reference.get();

if(activity != null){

activity.mTextView.setText("");

}

}

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTextView = (TextView)findViewById(R.id.textview);

loadData();

}

private void loadData() {

//...request

Message message = Message.obtain();

mHandler.sendMessage(message);

}

@Override

protected void onDestroy() {

super.onDestroy();

mHandler.removeCallbacksAndMessages(null);

}

}

使用mHandler.removeCallbacksAndMessages(null);是移除消息队列中所有消息和所有的Runnable。当然也可以使用mHandler.removeCallbacks();或mHandler.removeMessages();来移除指定的Runnable和Message。

四、线程造成的内存泄漏

对于线程造成的内存泄漏,也是平时比较常见的,如下这两个示例可能每个人都这样写过:

//——————test1

new AsyncTask<Void, Void, Void>() {

@Override

protected Void doInBackground(Void... params) {

SystemClock.sleep(10000);

return null;

}

}.execute();

//——————test2

new Thread(new Runnable() {

@Override

public void run() {

SystemClock.sleep(10000);

}

}).start();

上面的异步任务和Runnable都是一个匿名内部类,因此它们对当前Activity都有一个隐式引用。如果Activity在销毁之前,任务还未完成, 那么将导致Activity的内存资源无法回收,造成内存泄漏。正确的做法还是使用静态内部类的方式,如下:

static class MyAsyncTask extends AsyncTask<Void, Void, Void> {

private WeakReference<Context> weakReference;

public MyAsyncTask(Context context) {

weakReference = new WeakReference<>(context);

}

@Override

protected Void doInBackground(Void... params) {

SystemClock.sleep(10000);

return null;

}

@Override

protected void onPostExecute(Void aVoid) {

super.onPostExecute(aVoid);

MainActivity activity = (MainActivity) weakReference.get();

if (activity != null) {

//...

}

}

}

static class MyRunnable implements Runnable{

@Override

public void run() {

SystemClock.sleep(10000);

}

}

//——————

new Thread(new MyRunnable()).start();

new MyAsyncTask(this).execute();

这样就避免了Activity的内存资源泄漏,当然在Activity销毁时候也应该取消相应的任务AsyncTask::cancel(),避免任务在后台执行浪费资源。

五、资源未关闭造成的内存泄漏

对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。

❿ android 怎样处理内存泄露

在用java开发android,activity,service,对象生存周期参看官方文档,在不存在内部类给外部使用时,或者静态内部类,结束时不用管,super.onDestroy()后肯定回收了;如果在本activity(or server )结束应该被回收了,还被外部持有一个其context的对象,就会导致不能回收。不过这样的MemoryLeak在引用结束后也能回收的,单进程多线程,比如里面使用了Runnalbe,其周期也不超过Application。如果你自己重写了Application类,注意下引用。c/c++ 的NDK开发,以及驱动开发,推荐qq40289072答案

热点内容
手机如何给u盘加密 发布:2025-08-20 12:56:30 浏览:671
自动更新源码 发布:2025-08-20 12:48:36 浏览:743
已关联的qq为什么还要验证密码 发布:2025-08-20 12:46:01 浏览:814
c语言vector用法 发布:2025-08-20 12:46:00 浏览:460
lol脚本代练封号 发布:2025-08-20 12:44:39 浏览:57
时空幻境安卓版哪里有 发布:2025-08-20 12:43:43 浏览:288
解压抠画妆 发布:2025-08-20 12:41:34 浏览:844
华彩人生电脑版无法连接服务器 发布:2025-08-20 12:26:41 浏览:984
xp脚本错误 发布:2025-08-20 12:11:19 浏览:845
租用服务器有什么优势 发布:2025-08-20 12:06:32 浏览:872