前面看了一下如何看了延时方面的分析步骤,这里在给出查看内存占用方面的,分析工具用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下:
选中自己的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的并不是很难.