Android View 内存性能分析学习 <2>

来源:互联网 发布:淘宝童装店铺介绍大全 编辑:程序博客网 时间:2024/04/30 01:24

前面看了一下如何看了延时方面的分析步骤,这里在给出查看内存占用方面的,分析工具用eclipse的allocation Tracker工具.

下面盘是我做的一个测试程序:

http://pan.baidu.com/s/1gdSIi6f

主要用一个View来测试:

DurianView.java:

/**   * @Title: DurianView.java * @Package com.durian.view * @Description: TODO * @author zhibao.liu from durian organization * @date 2015-12-28 下午06:25:33 * @version V1.0   */package com.durian.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RadialGradient;import android.graphics.Rect;import android.graphics.Shader;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.view.View;import com.durian.durianperformanceview.R;import com.durian.utils.DurianUtils;/** * @ClassName: DurianView * @Description: TODO * @author zhibao.liu Freelancer * @email warden_sprite@foxmail.com * @date 2015-12-28 下午06:25:33 *  */public class DurianView extends View {    private final static String TAG = "DurianView";    private TypedArray mTypeArray;    private String mDurianText;    private float mDurianTextWidth;    private float mDurianTextSize;    private int mDurianLeft;    private int mDurianRight;    private int mDurianPosition;    private Paint mPaint;    private Bitmap mBitmap;    private Shader mRadialGradient = null;    private Paint mRadialPaint;    public DurianView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        // TODO Auto-generated constructor stub    }    public DurianView(Context context, AttributeSet attrs) {        super(context, attrs);        // TODO Auto-generated constructor stub        initView(context,attrs);                if(!isInEditMode()){            setLayerType(View.LAYER_TYPE_NONE, null);        }    }    public DurianView(Context context) {        super(context);        // TODO Auto-generated constructor stub    }        private void initView(Context context,AttributeSet attrs){                mTypeArray = context.obtainStyledAttributes(attrs,                R.styleable.durian_view);        mDurianText = mTypeArray.getString(R.styleable.durian_view_durian_text);        mDurianTextSize = mTypeArray.getInteger(                R.styleable.durian_view_durian_textsize, 16);        mDurianLeft = mTypeArray.getInteger(                R.styleable.durian_view_durian_leftpadding, 0);        mDurianRight = mTypeArray.getInteger(                R.styleable.durian_view_durian_rightpadding, 0);        mDurianPosition = mTypeArray.getInteger(                R.styleable.durian_view_durian_labelpos, 0);        mPaint = new Paint();        mPaint.setColor(Color.RED);        mPaint.setTextSize(DurianUtils.px2sp(context, mDurianTextSize));        mDurianTextWidth = mPaint.measureText(mDurianText);        Drawable map = mTypeArray                .getDrawable(R.styleable.durian_view_durian_src);        mBitmap = DurianUtils.drawableToBitmap(map);        // 创建RadialGradient对象        // 第一个,第二个参数表示渐变圆中心坐标        // 第三个参数表示半径        // 第四个,第五个,第六个与线性渲染相同        mRadialGradient = new RadialGradient(250, 250, 100, new int[] {                Color.GREEN, Color.RED, Color.BLUE, Color.WHITE }, null,                Shader.TileMode.REPEAT);        mRadialPaint = new Paint();        mRadialPaint.setShader(mRadialGradient);            }    public void updateDraw() {//        postInvalidate();        invalidate();    }    @Override    protected void onDraw(Canvas canvas) {        // TODO Auto-generated method stub        super.onDraw(canvas);//        canvas.clipRect(new Rect(0, 0, (int) (50 + mDurianTextWidth), 50 + 5));        canvas.drawText(mDurianText, 50, 50, mPaint);        canvas.drawLine(10.0f, 50.0f, 100.0f, 50.0f, mPaint);//        canvas.drawBitmap(mBitmap, 0, 55, mPaint);        // canvas.drawCircle(250f, 250f, 100f, mPaint);        canvas.drawCircle(250f, 250f, 100f, mRadialPaint);        for(int i=0;i<1000;i++){            canvas.drawCircle(250f+10*i, 250f+10*i, 100f, mRadialPaint);            /*Drawable map = mTypeArray            .getDrawable(R.styleable.durian_view_durian_src);            mBitmap = DurianUtils.drawableToBitmap(map);*/            canvas.drawBitmap(mBitmap, 0+1*i, 55+1*i, mPaint);        }            }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        // TODO Auto-generated method stub        super.onSizeChanged(w, h, oldw, oldh);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        // TODO Auto-generated method stub        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int minw = getPaddingLeft() + getPaddingRight()                + getSuggestedMinimumWidth();        int w = resolveSizeAndState(minw, widthMeasureSpec, 1);        int minh = MeasureSpec.getSize(w) - (int) mDurianTextWidth                + getPaddingBottom() + getPaddingTop();        int h = resolveSizeAndState(MeasureSpec.getSize(w)                - (int) mDurianTextWidth, heightMeasureSpec, 0);        setMeasuredDimension(w, h);    }}


注意上面程序onDraw方法里面的.

@Override    protected void onDraw(Canvas canvas) {        // TODO Auto-generated method stub        super.onDraw(canvas);//        canvas.clipRect(new Rect(0, 0, (int) (50 + mDurianTextWidth), 50 + 5));        canvas.drawText(mDurianText, 50, 50, mPaint);        canvas.drawLine(10.0f, 50.0f, 100.0f, 50.0f, mPaint);//        canvas.drawBitmap(mBitmap, 0, 55, mPaint);        // canvas.drawCircle(250f, 250f, 100f, mPaint);        canvas.drawCircle(250f, 250f, 100f, mRadialPaint);        for(int i=0;i<1000;i++){            canvas.drawCircle(250f+10*i, 250f+10*i, 100f, mRadialPaint);            /*Drawable map = mTypeArray            .getDrawable(R.styleable.durian_view_durian_src);            mBitmap = DurianUtils.drawableToBitmap(map);*/            canvas.drawBitmap(mBitmap, 0+1*i, 55+1*i, mPaint);        }            }

主要关注for循环里面的.

按照上面的修改,运行程序:

<1> : 让eclipse切换DDMS下:

选中自己的app进程,如上!

<2> : 然后切换右边的allocation tracker选项下:

点击"Start Tracking",然后"Get allocation" :

上面的信息,我发现每次都有,应该是一些其他方面的信息,和APP本身没有直接关系.

然后点击"stop tracking"按钮.


<3> : 下面正式开始,操作app里面的Button之前,先点起"Start tracking" , 然后点击界面的Button,启动另外一个带自定义View的Activity,然后点击"Stop Tracking" ,继续点击"Get Allocation" 即可:

下面其实还有很多信息列表.Allocation Size 是对应右边项所消耗的内存大小.

然后修改一下程序:

for(int i=0;i<10;i++){            canvas.drawCircle(250f+10*i, 250f+10*i, 100f, mRadialPaint);            Drawable map = mTypeArray            .getDrawable(R.styleable.durian_view_durian_src);            mBitmap = DurianUtils.drawableToBitmap(map);            canvas.drawBitmap(mBitmap, 0+1*i, 55+1*i, mPaint);        }

上面的循环次数需要改一下,如果还是保持1000,APP直接就会崩溃.这里暂时改成10次.

下面还有很多,内存量猛增.


下面我们增加一个过滤的条件:

就能够直观看到自己的那几个类所需要的内存,但是这个内存只是计算它创建时所消耗的,不会计算它后面update的部分.所以感觉在创建的时候增加内存消耗,他们的allocation size才会增大. onDraw方面里面不断申请内存空间,只会增加虚拟机dalvk部分不断消耗内存,增大了它的内存大小,所以:

更能够反映整个APP的内存开销情况.当然com.durian是分的更细了,方便程序定位.


在把程序修改一下:

for(int i=0;i<100;i++){            canvas.drawCircle(250f+10*i, 250f+10*i, 100f, mRadialPaint);            Drawable map = mTypeArray            .getDrawable(R.styleable.durian_view_durian_src);            mBitmap = DurianUtils.drawableToBitmap(map);            canvas.drawBitmap(mBitmap, 0+1*i, 55+1*i, mPaint);        }

直接运行程序:

直接崩溃,爆出OOM的.


通过分析上面的程序,对于OOM的定位还是非常容易的,只要掌握分析方法和思路,已经定位目标,查出导致OOM的并不是很难.









0 0
原创粉丝点击