精华内容
下载资源
问答
  • 最近做android 上图标矢量化工作,选取SVG格式做为矢量化方案,方法和微信开发SVG类似,最后转换SVG文件生成java代码drawable类,过程下次再说。android中读取java代码绘制记录,用canvas绘制。在这里遇到个问题,在...

    最近做android 上图标矢量化工作,选取SVG格式做为矢量化方案,方法和微信开发SVG类似,最后转换SVG文件生成java代码drawable类,过程下次再说。android中读取java代码绘制记录,用canvas绘制。在这里遇到个问题,在用canvas绘制图片时,如果对同一个view绘制多次,会使native内存不断增长,native里内存不能释放,经过排查,最后发现是默认使用硬件加速导致的,当给使用SVG的view设置硬件加速关闭,使用软件渲染可以解决问题。

     view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    

    在此寻找原因,原来是这样的:

    以复杂的shapes,path和旋转为例,这些绘制都会用到纹理的遮罩。每当你创建或者修改一个path,硬件渲染过程都会创建一个新的遮罩,这耗费的代价是相当大的。每当修改一次bitmap的内容,(用canvas绘制最后还是会得到bitmap)当你下次再绘制它的时候都会以GPU的纹理形式上传一次。可能是这些导致native内存的增加

    在此记录使用硬件加速的一些要点

      从Android 3.0开始,Android 2D的绘制流程就设计为能够更好地支持硬件加速。使用GPU的View在Canvas上进行画的操作时都会使用硬件加速。在最新的Android版本里,图形硬件加速及绘制技巧得到了更好的提升,51CTO特约了最牛网站长作为本站专栏作者,为各位网友撰写Android 4.0开发相关文章。

    1.Android 4.0硬件加速的使用

    1.1 硬件加速的控制级别

    启用硬件加速的最简单方法就是为整个系统打开硬件加速的全局设置。如果你的程序是标准View或者是Drawable 则硬件加速的全局设这并不会造成不良的影响。然而硬件加速并不支持所有2D画的操作,所以开启硬件加速可能会对使用自定义组件的应用程序造成影响,问题常常表现在不可见的元素异常和错误的像素渲染,为了解决这个问题Android可以让你选择启动

    1.1.1 Application级别

    或者禁用以下级别的硬件加速:Application Activity Window 和 View 。

    在你的Android Manifest文件中添加 属性标记,以便为整个应用程序使用硬件加速。

    1.1.2 Activity级别

    如果你的应用程序不能在Application应用级别表现良好的话,则可以使用对Activity进行单独控制。要启动或者禁用一个Activity的硬件加速,你可以使用activity的android:hardwareAccelerated属性。下面的一个列子使整个Application启用硬件加速,但是对一个Activity禁止使用硬件加速。

    1.1.3 Window级别

    如果你需要更细粒度的控制,你可以通过如下代码给window进行加速。

    getWindow().setFlags( 
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, 
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); 
    

    注意:现阶段你不能在Window级别对它禁用硬件加速。

    1.1.4 View级别

    我们可以对单独的View在运行时阶段禁用硬件加速。我们可以使用如下代码:

    myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    注意:现阶段不能够在View级别进行硬件加速。

    1.2 判断一个View是否已经启用了硬件加速

    有时候我们需要知道一个应用程序是否已经启用了硬件加速,特别是针对一些自定义控件。因为你的应用程序做了很多自定义“画”的操作,但并不是所有的过程都支持新的“画”的渲染过程。

    有两种不同的方法来检查Application是否启用了硬件加速:

    1.2.1 使用View.isHardwareAccelerated() 如果返回true则可以说明这个View所在的窗口已经启用了硬件加速。

    1.2.2 Canvas.isHardwareAccelerated() 如果返回true则说明这个Canvas已经启用了硬件加速。

    如果你必须要在你的绘画代码中进行是否已经加速的检查,如果可能的话请使用Canvas.isHardwareAccelerated()来代替View.isHardwareAccelerated()。当一个View是存在于一个已经加速的Windows上时,任然可以使用没有硬件加速的Canvas进行绘画,这场发生在,比如,当我们把一个View画到Bitmap上然后用作缓存。

    2.Android 4.0的绘制模型

    当开启了硬件加速,Android框架将会使用一种新的绘制模型,这种模型将会使用显示列表把你的应用显示到屏幕上。要完全理解显示列表和他们如何影响你的应用程序,理解Android 4.0如何在非硬件加速的情况下如何绘制Views是很有必要的,下面将分别介绍软件加速和硬件加速。

    2.1基于软件的绘制模型

    在基于软件绘制模型中,View的绘制遵循以下两步:1.使整个控件层级无效。2.对层级进行绘制。

    当一个应用程序需要更新它UI的一部分时,它将会调用内容发生改变的View的invalidate()方法(或者invalidate的变体)。Invalidate的消息按照View的层级关系向上传递用以计算需要重画的部分(即脏区域)。然后Android系统会对和脏区域有交集的所有View进行绘制,不幸的是这种模型中有两个缺点:

    2.1.1 在这种模型中当在不同的层进行画的时候,会额外执行很多代码。例如一个Button是位于另外一个View之上,当对Button调用 Invalidate()时,Android就会对这个View进行重绘,即便这个View没有发生任何变化。

    2.1.2 第二个问题是这种绘制模型会隐藏你Application中的Bug。因为Android系统会对和脏区域有交集的View进行重绘,在这种情况下如果一个view的内容发生了改变,即便这个View的Invalidate()的方法并没有得到调用,它也可能被重绘。你便会依赖调用了invalidate()的其他的控件以便获得正确的行为,因此每当你的Application发生改变时,这种行为多要随之发生改变。也是基于次因,在你的自定义控件中你必须不断地调用invalidate()方法,当你的数据或者是状态会影响View的绘制代码时。

    注意:Android的View当它们的属性发生改变时会自动的调用Invalidate()。比如,你改变一个 Textview的背景或者是它的文本。

    2.2 基于硬件加速模型

    Android 系统仍然通过invalidate()和draw()去请求屏幕更新和重新渲染,但是实际处理画的方式是不同的。不是立即执行画的命令,Android而会将所有画的命令记录在一个显示列表里面,这个显示列表包含了输出的View层级的绘制代码。还有一个优化就是Android在显示列表中只会记录和更新显示层级中通过调用invalidate()函数被标记为“脏”的view。没有被请求刷新的view可以通过重新请求先前的显示列表以便重画。新的绘制模型包括有三个步骤:1.禁用整个View层级。2.记录和更新显示列表。3.绘制显示列表。

    使用这个模型你不能依赖一个View和脏区域有交集就会执行draw()方法。要确保Android系统记录了一个View的显示列表,你必须调用invalidate()方法,如果忘记了调用刷新,会使View即便是发生了改变后也会看起来相同,这是一个比较容易发现bug的方式。

    使用显示列表的方式对动画的表现也是很有好处的,因为设置指定的属性值,比如透明度或者旋转,就不需要请求刷新目标View(这将自动执行)。这项优化也应用于有显示列表的Views(启用了硬件加速的View),例如,现在有一个LinearLayout包含了一个ListView和Button,listview在button的上面。这时候LinearLayout的显示列表如下所示:

    ◆DrawDisplayList(ListView) ;

    ◆DrawDisplayList(Button) ;

    假设你现在你想更新这个Listview的不透明度,在设置Listview的 setAlpha(0.5f) 属性之后,LinearLayout的显示列表应该包含如下:

    ◆ SaveLayerAlpha(0.5)

    ◆ DrawDisplayList(ListView)

    ◆ Restore

    ◆ DrawDisplayList(Button)

    这时候绘制Listview的复杂过程就会省略了,取而代之的是简单的更新了LinearLayout的显示列表。如果一个应用程序并没有启用硬件加速,Listview和它的父view的画的代码都会重新执行。

    3.Android 4.0 View的层

    3.1层的分类

    所有的Android版本都有能力对离屏缓冲进行渲染,或者是使用View的绘制缓冲,或者是使用Canvas.saveLayer()函数。离屏缓冲或者Layer能够有很多种应用,例如能使处理复杂view的动画效果或者应用一些合成效果都有更好地表现。例如你可以通过Canvas.saveLayer()的方式来对View做一个渐入渐出效果同时把它渲染到Layer中,然后再加上不透明效果合成后显示到屏幕上。

    由Android 3.0开始你就能够通过View.setLayerType()方法对何时以及如何使用层有了更多的控制,这个API具有两个参数一个是你想使用的层类型,另外一个是可选参数Paint表明了Layer是如何被叠加的。你可以把Paint参数应用到颜色过滤上,特别是混合模式或者是对一个layer进行不透明效果。一个View可以使用如下的三种layer类型之一:

    ◆ LAYER_TYPE_NONE: 这个View将被按普通的方式进行渲染,但是不会返回一个离屏的缓冲,这个是默认的行为。

    ◆ LAYER_TYPE_HARDWARE:如果这个应用被硬件加速的话,这个View将会在硬件中渲染为硬件纹理,如果应用程序并没有被硬件加速,则其效果和LAYER_TYPE_SOFTWARE是相同的。

    ◆ LAYER_TYPE_SOFTWARE: 此View 通过软件渲染为一个bitmap。

    3.2 层的使用

    使用层的类型取决于你的目的:

    3.2.1 性能:使用硬件层来渲染一个View成为硬件纹理。一旦一个View被渲染为一个层,它的绘制代码将不会得到执行,直到你调用了invalidate()函数。对于一些动画,比如透明动画可以直接应用到一个层上,这是GPU最有效率的使用方式。

    3.2.2 显示效果:使用硬件或者软件层和Paint来对一个View进行特殊的视觉处理,例如你可以对一个View通过使用ColorMatrixColorFilter来实现黑白效果。

    3.2.3 兼容性:使用软件层类型会强制使一个view在软件中被渲染。如果一个view是硬件加速的话(比如你设置整个应用程序是硬件加速的话),同时有渲染的问题,这是一种很简单的方式来限制硬件绘制流程。

    3.3 View的层和动画的关系

    当你的应用程序已经使用了硬件加速的话,硬件层能够带来更为快速和更为平滑的动画效果。当对一个复杂的View进行动画操作时,因为要进行很多的画操作,所以并不可能总是能达到60帧每秒。在这种情况下可以通过硬件层来渲染为硬件纹理来提高性能。硬件纹理操作可以用作对一个view进行动画操作,当进行动画的时候可以减少对View自身频繁的重绘。除非你改变这个view的属性(调用invalidate()方法)或者你手动的调用invalidate()。如果在你的应用中运行一个动画,但是并没有得到你想要的平滑效果,可以考虑为你要动画的view开启硬件层。

    当一个View通过硬件层返回时,当所有的层叠加后最终的画面显示在屏幕时,View一些属性会被同时被处理。设置这些属性是十分有效率的,因为他们不需要View去invalidate和重绘。如下的属性将影响层的叠加,设置这些属性将会使View自动请求刷新,而且不需要对View进行重绘。

    ◆alpha: 改变层的透明度。

    ◆x, y, translationX, translationY: 改变层的位置

    ◆scaleX, scaleY: 改变层的大小

    ◆rotation, rotationX, rotationY:在3D空间内改变层的方向

    ◆pivotX, pivotY: 指定它进行变形的原点位置

    这些属性是通过ObjectAnimator对象对一个view进行动画操作时所使用的,如果你想访问这些属性,直接调用这些属性的setter或者getter方法,例如想改变View的alpha则直接调用setAlpha()。如下的代码片段显示了一个View通过Y轴进行3D旋转。

    view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    ObjectAnimator.ofFloat(view, “rotationY”, 180).start();
    因为硬件层会消耗视频的内存,强烈的推荐你在作动画的时候启用他们,当动画完成了之后禁用他们,你可以通过动画监听来完成这些。代码如下:

    View.setLayerType(View.LAYER_TYPE_HARDWARE, null); 
    ObjectAnimator animator= 
      ObjectAnimator.ofFloat(view, "rotationY", 180); 
    animator.addListener(new AnimatorListenerAdapter() { 
    @Override 
    public void onAnimationEnd(Animator animation) { 
    view.setLayerType(View.LAYER_TYPE_NONE, null); 
    } 
    }); 
    animator.start(); 
    

    4 Android 4.0提示和技巧

    切换到硬件加速2D图形可以立即增强表现,但是你还是需要通过如下的建议来设计你的应用程序来更有效率的使用GPU。

    4.1 减少你程序中使用View的数量

    你系统中画的view的数量越多,你的程序就会越慢,在软件绘制的流程也是一样的,减少view的数量是优化你UI的一个最简单的方法。

    4.2 避免过多绘制

    不要过多的叠加层,当一个View被其他view完全遮挡住了的话,最好把被遮挡的view移除掉。如果你需要绘制不同的层做一个叠加效果的话,考虑把这些层合并为一个层。就现在的硬件来看,有一个好的经验就是动画的每帧不要绘制多余屏幕像素2.5倍的像素数量(bimap中的透明像素也计算在内)。

    4.3 不要在绘制的方法中创建绘制对象

    一个常见的错误就是当绘制方法被调用的时候,每次都要创建一个新的Paint或者Path。这将迫使垃圾回收器过于频繁的运行,这将对缓冲和硬件的绘制造成影响。

    4.4 不要过于频繁的修改形状

    以复杂的shapes,path和旋转为例,这些绘制都会用到纹理的遮罩。每当你创建或者修改一个path,硬件渲染过程都会创建一个新的遮罩,这耗费的代价是相当大的。

    4.5 不要过于频繁的修改bitmap

    每当修改一次bitmap的内容,当你下次再绘制它的时候都会以GPU的纹理形式上传一次。

    4.6 要小心使用alpha通道

    当你使用setAlpha ,AlphaAnimation或者ObjectAnimator设置一个View的透明效果时。它将需要2倍离屏的渲染缓冲填充率,当应用一个alpha到一个大的View上的时候,考虑设置view 层的类型为LAYER_TYPE_HARDWARE。

    其他一些可能的问题

    • EditText中文字的重叠
      在某些4.x的机器中,如果打开了硬件加速,EditText会出现奇怪的文字重叠的情况。

    这里写图片描述

    解决办法

    android:layerType=”software”  
    
    • 做的程序里有的时候会需要加载大图,但是硬件加速中 OpenGL对于内存是有限制的。如果遇到了这个限制,LogCat只会报一个Warning: Bitmap too large to be uploaded into a texture
      这时我们就需要把硬件加速关闭了。

    • 还有些自定义view遇到些奇怪的问题的时候,可以尝试关闭硬件加速

    最新对比发现造成内存泄漏是drawpath()这个函数,查看vectordrawable发现也是使用cachebitmap来绘制,所以没有泄漏,泄漏原因还要继续寻找

    引用文章

    http://zuiniuwang.blog.51cto.com/3709988/721798
    http://blog.csdn.net/icyfox_bupt/article/details/18732001

    展开全文
  • Context内存泄漏问题

    千次阅读 2018-05-28 20:26:14
    写的不错,里面有一段内容平时开发时候没有注意到,摘抄如下: 在项目中,我们经常会遇到使用单例模式或者静态static变量,虽然使用静态类或者静态变量很方便,但是也潜在很多的内存泄漏问题。6.1静态资源导致的...

    今天看了一篇介绍Context的文章,写的不错,里面有一段内容平时开发时候没有注意到,摘抄如下: 
    在项目中,我们经常会遇到使用单例模式或者静态static变量,虽然使用静态类或者静态变量很方便,但是也潜在很多的内存泄漏问题

    6.1静态资源导致的内存泄漏

    你可能遇到以下这段代码:

    public class MyCustomResource {
        //静态变量drawable
        private static Drawable drawable;
    
        public MyCustomResource(Context context) { //这个context对象就是Activity的Context
            Resources resources = context.getResources();
            drawable = resources.getDrawable(R.drawable.ic_launcher);
        }
    }

    请问,这段代码有什么问题?乍一看貌似没啥问题,挺好的啊!其实不然,主要的问题在于静态变量drawable这里,我们知道静态变量在整个应用的内存里只保存一份,一旦创建就不会释放该变量的内存,直到整个应用都销毁才会释放static静态变量的内存。可是以上drawable资源是由Context对象来获得,从而静态变量drawable会持有该Context对象的引用,也就意味着如果该Context对应的Activity退出finish掉的时候其实该Activity是不能完全释放内存的,因为静态变量drawable持有该Activity的Context。从而导致该Activity内存无法回收,导致内存泄漏隐患。因为Activity就是Context,所有Context的生命周期和Activity是一样长的,我们希望Activity退出时Context也释放内存,这样才不会导致内存泄漏隐患。那么以上这段代码是不安全的,如果代码必须要使用静态资源怎么办呢?其实我们可以这么修改:

    Context包括三种:Activity、Service和Application,一般而言Context对象都是Activity的context,在一篇我的这篇文章https://mp.csdn.net/postedit/80222796讲到,一般就不要用Activity的context,容易出现内存泄漏的问题,尽量使用Application的Context。

    public class MyCustomResource {
        //静态变量drawable
        private static Drawable drawable;
    
        public MyCustomResource(Context context) {
            Resources resources = (context.getApplicationContext()).getResources();
            drawable = resources.getDrawable(R.drawable.ic_launcher);
        }
    
    }

    这里我们修改成了使用getApplicationContext去获取App的资源。由上一小节可知getApplicationContext返回的对象是Application的Context,而Application的生命周期和整个应用是一样的,应用启动Application被创建,整个应用退出Application销毁。所以Application的Context的生命周期就是整个应用的生命周期,恰好可以用来获取静态资源。利用Application的Context就不会导致内存泄漏了。

    6.2 单例模式导致内存泄漏

    相信单例模式对开发者很有诱惑力吧!或多或少在项目中都有用过单例模式。你也可能见过一下这段代码:

    public class CustomManager {
        private static CustomManager sInstance;
        public static CustomManager getInstance(Context context) {
            if (sInstance == null) {
                sInstance = new CustomManager(context);
            }
            return sInstance;
        }
    
        private Context mContext;
        private CustomManager(Context context) {
            mContext = context;
        }
    }

    同样,以上代码也存在内存泄漏的隐患。因为单例模式使用的是静态类的方式,让该对象在整个应用的内存中保持一份该对象,从而减少对多次创建对象带来的资源浪费。同样的问题:在创建该单例的时候使用了生命周期端的Context对象的引用,如果你是在Application中创建以上单例的话是木有任何问题的。因为Application的Context生命周期是整个应用,和单例的生命周期一样,因此不会导致内存泄漏。但是,如果你是在Activity中创建以上单例的话,就会导致和6.1小节一样的问题—内存泄漏。所以我们同样可以将代码修改成如下:

    public class CustomManager {
        private static CustomManager sInstance;
        public static CustomManager getInstance(Context context) {
            if (sInstance == null) {
                sInstance = new CustomManager(context.getApplicationContext());
            }
            return sInstance;
        }
    
        private Context mContext;
        private CustomManager(Context context) {
            mContext = context;
        }
    }

    6.3 总结

    以后在使用Context对象获取静态资源,创建单例对象或者静态方法的时候,请多考虑Context的生命周期,一定要记得不要使用Activity的Context,切记要使用生命周期长的Application的Context对象。但是并不是所有情况使用Application的Context对象,比如第4小节,在创建Dialog,View控件的时候都必须使用Activity的Context对象。

    转载自:http://blog.csdn.net/feiduclear_up CSDN 废墟的树

    展开全文
  • 求大神指导:加载本地drawable中GIF文件,出现内存泄漏,怎么解决?
  • 内存泄漏常见原因总结

    千次阅读 2016-02-27 00:07:48
    内存泄漏常见原因总结1.非静态内部类的静态实例2.Activity的静态成员变量 Drawable Context Drawable的对象的内部Callback持有activity的引用,当Activity finish()之后,静态成员drawable始终持有这个Activity的...

    内存泄漏常见原因总结

    1.非静态内部类的静态实例

    public class MainActivityextends Activity
    {
             static Demo sInstance = null;
    
        @Override
        public void onCreate(BundlesavedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            if (sInstance == null)
            {
               sInstance= new Demo();
            }
        }
        class Demo
        {
        voiddoSomething()
        {
                   System.out.print("dosth.");
        }
        }
    }

    2.Activity的静态成员变量

    1. Drawable
    2. Context

    Drawable的对象的内部Callback持有activity的引用,当Activity finish()之后,静态成员drawable始终持有这个Activity的引用,导致内存释放不了。

    Context,Activity内部如果有一个Context的成员变量,将导致Context引用指向的Activity对象释放不了。

    public class MainActivity extends Activity {
        private static Context mContext;
    
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            ...
            mContext=MainActivity.this;
        }
    }

    3.Handler造成的内存泄漏

    3.1 Handler内存泄漏的原因

    public class MainActivity extends Activity {
        ...
        private Handler mHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                ...
            }
        };
        ...
    }

    大家平时开发中喜欢在Activity中直接new一个Handler的匿名内部类,这样造成匿名内部类持有一个外部类(通常是Activity)的引用(不然怎么更新ui),但是Handler常常伴随着一个执行耗时操作的异步线程(如下载多张图片),如果在完成耗时操作之前,Activity退出,异步线程持有handler的引用,handler持有Activity的引用,从而导致内存泄漏。

    3.2 防止Handler内存泄漏的措施

    通过程序逻辑来进行保护

    1. 在关闭Activity的时候,把线程也关了;
    2. 如果Handler是被delay的Message持有的引用,在Activity的onDestroy()方法中,调用Handler响应书的removeCallbacks()方法,把消息对象从消息队列移除就行了。

    将Handler声明为静态类

    • 静态类不持有外部类的引用,所以Activity可以被随意回收,代码如下:

      ...
      private static class MyHandler extends Handler {
          @Override
          public void handleMessage(Message msg) {
              ...
          }
      }
      ...

    使用弱引用

    当Activity在内存中的对象没有任何引用,使用弱引用会让Activity对象很容易被Gc回首。代码如下:

    ...
    private static class MyHandler extends Handler {
            WeakReference<CrmContactActivity> mReference;
    
            public MyHandler(CrmContactActivity activity) {
                mReference = new WeakReference<CrmContactActivity>(activity);
            }
    
            @Override
            public void handleMessage(Message msg) {
                final CrmContactActivity activity = mReference.get();
                if (activity == null || activity.isFinishing()) {
                    return;
                }
                if (msg.what == LOAD_MORE) {
                    activity.getCustomersByCompanyName(activity.companyName);
                } else if (msg.what == THE_END) {
                    activity.showViewIfHasCompanyName((ArrayList<CustomerModel>) activity.matchedCustomerList);
                }
            }
        }
        ...

    4.注册某个对象后没有反注册

    广播接收器注册后在Activity退出时忘了反注册,一些利用观察者模式的第三方开源库在使用时,忘了反注册(如EventBus)。
    正确代码如下:

        @Override
        protected void onDestroy() {
            EventBus.getDefault().unregister(this);
            super.onDestroy();
        }

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

    把大量对象的引用放入集合中,但我们不需要该对象时,记得从集合中将不需要的引用清理掉,同理,当对象不需要时,记得将对象的引用设置为null。

    6.资源文件未关闭

    最常见的是文件流执行完读写操作后,忘记关闭了输入流,输出流;数据库、Content Provider操作完后Cursor忘记了close等等。
    安全一点的方式是在写代码的时候,首先写完头尾,避免尾部关闭操作忘记了谢。

    7.代码不严谨

    • Bitmap对象使用完后,忘记了调用recycle()方法销毁;
    • 解析图片的时候忘记了设置采样率
    • 自定义View时TypedArray使用完后忘记调用recycle()方法释放内存
    • ListView的适配器类中没有复用convertView
    • 未采用软引用等

    8.关于内存泄漏的调试

    我有一篇博客介绍我开发过程中一次典型的内存泄漏案例,这个案例中介绍了内存泄漏检测工具MAT的使用,博客链接如下:

    MAT使用案例

    展开全文
  • 深入 android 内存泄漏

    2012-11-21 21:57:47
    Android 内存泄漏  android 自动垃圾回收机制,所以一般很少出内存泄露,但一泄露就很难查。  private static Drawable sBackground;     @Override  protected void onCreate(Bundle state) {     ...

    Android 内存泄漏

             android 自动垃圾回收机制,所以一般很少出内存泄露,但一泄露就很难查。

             private static 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); 
          }

         这段代码由于background 导致整个activity 不能够释放。当时我看了就不是很明白。textview 引用了activity ,activity 又引用了textview ,textview 引用了 background ,background是一个静态变量。 那应该也会回收掉 activity 和textview ,除了background 。 后来查看了 setBackgroundDrawable 方法才明白 。

       

     

        由于background 会通过成员变量  来反向引用了 textview 导致的。

      

        最近看同事的一段代码:

           

        onkeydown(keycode){
                 

               if(keycode == KeyEvent.keycode_back){

                     CustomDialog d = new CustomDialog(this);

                      ............
       }

        }

        反复点击backkey 会不停的 new dialog。 而d 又引用了activity。会不会导致不释放了。 

       

        通过eclipse自带的工具测试。内存测试。

       不停的点击backkey ,totalsize 会从1.47左右升到 1.52左右 然后会被垃圾回收一次。 又回落到1.47左右。


       

       


    展开全文
  • Android 内存泄漏——context泄漏

    千次阅读 2012-11-07 19:56:39
    Context泄漏。  这是一个很隐晦的内存泄露的情况。先看一个Android官网提供的例子:  private static Drawable sBackground; @Override protected void onCreate(Bundle state) { super.onCreate(state); ...
  • (转)Context内存泄漏问题

    千次阅读 2015-08-11 10:37:04
    在项目中,我们经常会遇到使用单例模式或者静态static变量,虽然使用静态类或者静态变量很方便,但是也潜在很多的内存泄漏问题。6.1静态资源导致的内存泄漏你可能遇到以下这段代码:public class MyCustomResource {...
  • 解决内存泄漏案例

    2016-04-13 20:47:40
    要点分析 1. 通过代码分析,我们发现在计时器界面中,采用了...drawable = getApplicationContext().getResources() .getDrawable(R.drawable.countdown_sandglass_anim);  mDustFallStart.setBackgroun
  • 经常导致内存泄漏的一些原因: keeping a long-lived reference to a Context.持有一个context的对象,从而gc不能回收。 1,一个View,的作用域超出了所在的Activity的作用域,比如一个static的View或者 把一个View ...
  • 内存泄漏是安卓开发中常见的一种情况,其原因本质上是一个生命周期更长的对象持有了一个本该回收对象的引用,几种具体的表现已经有很多博客进行了分析,比如全局/单例对象,集合,内部类,线程,资源对象等等。...
  • 我知道这是内存泄漏,或者没有写close的问题。于是根据报错日志加了response.body().close()但是好像没用还是报这个错误。有大神知道这是什么原因吗? 我的网络请求代码如下请问如何修复才能避免上面这个报错呢? ...
  • 先看一个例子: ... private static Drawable sBackground; @Override protectedvoid onCreate(Bundle state){ super.onCreate(state); TextView label =newTextView(this); label.setTex...
  • 避免Drawable保持引用的内存泄露

    千次阅读 2012-06-19 10:09:45
    Android应用在T-MobileG1上被限制只能使用16MB的内存。这对于手机来说已经是很大的内存了但对于很多开发者来说却仍然...作为工作的一部分,在开发Android应用的时候我碰到了很多内存泄漏问题,而绝大部分都出自于
  • 看到了这么一段话View持有Activity引用public class MainActivity extends Activity { private static Drawable mDrawable; @Override protected void onCreate(Bundle saveInstanceState) { super.onCreat...
  • drawable不能json化

    2017-01-03 10:41:00
    最近做项目的时候遇到了一个挺尴尬的问题,log输出的信息是满满内存泄漏,连系统也卡住了,找了半天的原因,都不知道哪里内存泄漏,迫不得已要把之前做的步数一步一步返回然后调试,最后发现使用Gson的toJson的方法...
  • Gif-Load-ReTry-Refresh:只需要一张Gif图,一行代码支持初次加载,重试加载,加载后再次刷新原理 :遍历View树,在Framelayout中动态插入和移除加载布局,与生命周期绑定,避免内存泄漏;功能 :目前支持在...
  • Android 内存泄露

    2015-11-18 17:56:00
    当出现对Activity、View或drawable等类的对象长期持有无用的引用,就会造成被引用的对象无法在GC时回收,而是长期占用堆空间,此时就会发生内存泄漏。简单来说,就是保留下来却永远不再使用的对象引用。 2、内存...
  • 当出现对Activity、View或drawable等类的对象长期持有无用的引用,就会造成被引用的对象无法在GC时回收,而是长期占用堆空间,此时就会发生内存泄漏。简单来说,就是保留下来却永远不再使用的对象引用。 2、内存...
  • 当出现对Activity、View或drawable等类的对象长期持有无用的引用,就会造成被引用的对象无法在GC时回收,而是长期占用堆空间,此时就会发生内存泄漏。 简单来说,就是保留下来却永远不再使用的对象引用。 2、内存...
  • 当出现对Activity、View或drawable等类的对象长期持有无用的引用,就会造成被引用的对象无法在GC时回收,而是长期占用堆空间,此时就会发生内存泄漏。 简单来说,就是保留下来却永远不再使用的对象引用。 2、内存...
  • Android内存泄露的整理

    2013-08-12 17:59:32
    当出现对Activity、View或drawable等类的对象长期持有无用的引用,就会造成被引用的对象无法在GC时回收,而是长期占用堆空间,此时就会发生内存泄漏。简单来说,就是保留下来却永远不再使用的对象引用。 2、内存溢出...
  • 3.避免Content内存泄漏,比如在4.0.1之前的版本上不要讲Drawer对象置为static。当一个Drawable绑定到了View上,实际上这个View对象就会成为这个Drawable的一个callback成员变量,上面的例子中静...
  • 解决内存释放问题

    2020-12-01 12:28:10
    在上一次提交代码中已经解决了大部分内存泄漏的问题「#251 」,但是在最近的跟踪中发现 App 对内存的消耗很大经常 OOM。最终定位到 SVGAVideoEntity。 <p><img alt="image" src=...
  • 1. 硬件加速导致的自定义drawable内存泄漏 摘自:硬件加速导致的自定义drawable内存泄漏 原因 在用canvas绘制图片时,如果对同一个view绘制多次,会使native内存不断增长,native里内存不能释放,经过排查,...
  • 注意:用的时候需要在activity销毁之前需要把,mHandler中消息清空,否则会造成内存泄漏,因为mHandler 会对外部类有一个引用,也就是CoolImageView,然后CoolImageView 又引用当前的Activity所以会造成内存泄漏 ...

空空如也

空空如也

1 2
收藏数 40
精华内容 16
关键字:

drawable内存泄漏