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

前面看了一下如何看了延时方面的分析步骤,这里在给出查看内存占用方面的,分析工具用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 [email protected]
 * @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下:

Android View 内存性能分析学习 <2>_第1张图片

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

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

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

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

然后点击"stop tracking"按钮.


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

Android View 内存性能分析学习 <2>_第2张图片

下面其实还有很多信息列表.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);
        }

直接运行程序:

Android View 内存性能分析学习 <2>_第3张图片

直接崩溃,爆出OOM的.


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










你可能感兴趣的:(Android View 内存性能分析学习 <2>)