短跑路径效果使屏幕缓慢

时间:2017-03-22 06:37:35

标签: android performance android-custom-view

我正在尝试使用由点组成的同心圆来制作自定义视图。我附上了截图供参考。直到时间自定义视图只有同心圆它工作正常但是一旦我应用DashPathEffect它会使整个屏幕缓慢,当你试图打开或关闭导航抽屉时,这是很好观察。我已经附上了以下日志。 以下是解释问题的视频的链接 https://youtu.be/5Mgz4QhXaQI

自定义视图

public class ConcentricCircularView extends View {
    private static final String TAG = "ConcentricCircularView";
    private Paint paint;
    private Context context;

    public ConcentricCircularView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(Utils.dipToPixels(context,getResources().getDimension(R.dimen.d1)));
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setAntiAlias(true);
        this.context=context;

    }

    int onDrawCounter = 0;
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.e(TAG, "Actual radius"+getWidth());
        int radius= (int) (getWidth()/3);
        int distanceBtwDots= (int) Utils.dipToPixels(context,getResources().getDimension(R.dimen.d10));
        Log.e(TAG, "Counter: "+onDrawCounter++);
        for (int i=0;i<10;i++){
            DashPathEffect dashPath = new DashPathEffect(new float[]{1,distanceBtwDots}, 0);
            paint.setPathEffect(dashPath);
//            Log.e(TAG, "Current radius "+radius);
            canvas.drawCircle(getWidth()/2, getHeight()/2,radius, paint);
            radius= (int) (radius+Utils.dipToPixels(context,getResources().getDimension(R.dimen.d15)));
            distanceBtwDots= (int) (distanceBtwDots+Utils.dipToPixels(context,getResources().getDimension(R.dimen.d1)));

        }


    }
}

从控制台登录

[![03-22 12:01:38.734 19919-19919/com.lief.smartwallet D/ViewRootImpl: ViewPostImeInputStage processPointer 0
03-22 12:01:38.834 19919-19919/com.lief.smartwallet D/ViewRootImpl: ViewPostImeInputStage processPointer 1
03-22 12:01:39.474 19919-19919/com.lief.smartwallet I/Choreographer: Skipped 34 frames!  The application may be doing too much work on its main thread.
03-22 12:01:43.184 19919-19919/com.lief.smartwallet I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@e65187c time:662629
03-22 12:01:47.559 19919-19919/com.lief.smartwallet D/ViewRootImpl: ViewPostImeInputStage processPointer 0
03-22 12:01:47.679 19919-19919/com.lief.smartwallet D/ViewRootImpl: ViewPostImeInputStage processPointer 1

enter image description here

enter image description here

2 个答案:

答案 0 :(得分:1)

你必须保持一个boolean,表明你是否必须画一些东西。目前,您在每次迭代时都不必要地绘制完全相同的东西。

如Romain Guy here所述:

  

通常,硬件图层应设置在绘制成本高昂且视图内容不会经常更改的视图上。

public class ConcentricCircularView extends View {
    ...
    private boolean shouldDraw = true;
    ...

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (shouldDraw) {
            shouldDraw = false;
            setLayerType(View.LAYER_TYPE_HARDWARE, null);
            // draw your view here
        }
    }

    public void setShouldDraw(boolean shouldDraw) {
        this.shouldDraw = shouldDraw;
    }
}

答案 1 :(得分:0)

问题是在onDraw中做了不必要的工作。这种方法每秒最多被调用60次。因此,在此方法中访问资源或创建对象会损害性能。这是一个固定版本:

public class ConcentricCircularView extends View {
    private static final int COUNT = 10;
    private Paint paint;
    private DashPathEffect[] dashPaths = new DashPathEffect[COUNT];
    private int halfWidth, halfHeight, radius;
    private int dimen15;

    public ConcentricCircularView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        // Get the dimensions.
        int dimen1 = dipToPixels(getResources().getDimension(R.dimen.d1));
        int dimen10 = dipToPixels(getResources().getDimension(R.dimen.d10));
        dimen15 = dipToPixels(getResources().getDimension(R.dimen.d15));
        // Setup the path effects;
        for (int i=0; i<COUNT; i++) {
            dashPaths[i] = new DashPathEffect(
                    new float[]{ 1, dimen10 + dimen1 * i }, 0);
        }
        // Setup the paint.
        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(dimen1);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setAntiAlias(true);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        halfWidth = w / 2;
        halfHeight = h / 2;
        radius = w / 3;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i=0; i<COUNT; i++) {
            paint.setPathEffect(dashPaths[i]);
            canvas.drawCircle(halfWidth, halfHeight, radius + dimen15 * i, paint);
        }
    }

    private int dipToPixels(float value) {
        final float scale = getResources().getDisplayMetrics().density;
        return (int) (value * scale + 0.5f);
    }
}