调用BitmapDrawable.draw(Canvas画布)时应用程序崩溃

时间:2017-04-17 16:42:57

标签: android canvas bitmap picasso

我有这样的代码:

@Override
public void onDrawOver(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
    drawGradient(canvas, parent);
    drawStages(canvas, parent);
}

private void drawStages(final Canvas canvas, RecyclerView parent) {
    final int parentLeft = parent.getPaddingLeft();
    final int parentRight = parentLeft + mLeftPadding + mIconSize + mRightPadding;

    int childCount = parent.getChildCount();
    for (int i = 0; i < childCount - 1; i++) {
        View child = parent.getChildAt(i);

        LineupLayoutManager.LayoutParams params =
                (LineupLayoutManager.LayoutParams) child.getLayoutParams();

        final int parentTop = child.getTop() + params.topMargin;
        final int parentBottom = child.getBottom() + params.bottomMargin;
        int height = parentBottom - parentTop;

        final int paddingVertical = Math.round((height - mIconSize) / 2);

        try {
            String link = findPlaceById(params.getPlaceId(),mStageList).getImg();
            Picasso.with(context).load(link).resize(150,150).into(new Target() {
                @Override
                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                    final Drawable drawable = new BitmapDrawable();
                    drawable.setBounds(parentLeft + mLeftPadding, parentTop + paddingVertical,
                            parentRight - mRightPadding, parentBottom - paddingVertical);
                    Canvas canvas1 = new Canvas(bitmap);
                    drawable.draw(canvas1);
                }

                @Override
                public void onBitmapFailed(Drawable errorDrawable) {

                }

                @Override
                public void onPrepareLoad(Drawable placeHolderDrawable) {

                }
            });
        } catch (IndexOutOfBoundsException e) {
            Log.e(LOG_TAG, Log.getStackTraceString(e));
        }
    }
}

整个代码位于从RecyclerView.ItemDecoration扩展的Class中 问题是,当我执行它时,应用程序崩溃时出现此错误:

  

致命信号11(SIGSEGV),代码1,故障地址0x58 in tid 17542

我也尝试将bitmap.draw放入runOnUIThread()但没有成功。

经过一番研究,我发现毕加索在某种程度上干扰了画布。这意味着如果我把这些东西放在毕加索方法之外,一切都运转正常。

1 个答案:

答案 0 :(得分:0)

我现在只是假设,但似乎你早些时候存储了对canvas的引用。当您收到Bitmap后,此Canvas可能已经以某种方式失效。

代替您的实施,存储对Drawable的引用,并请求重新View。然后在onDraw()内将Drawable绘制为作为参数提供的Canvas

尝试根据您的喜好调整以下实现。

BitmapDrawable drawable = null;

private void drawStages(Canvas canvas, RecyclerView parent) {
    if (drawable != null) {
        int parentLeft = parent.getPaddingLeft();
        int parentRight = parentLeft + mLeftPadding + mIconSize + mRightPadding;

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount - 1; i++) {
            View child = parent.getChildAt(i);

            LineupLayoutManager.LayoutParams params =
                    (LineupLayoutManager.LayoutParams) child.getLayoutParams();

            int parentTop = child.getTop() + params.topMargin;
            int parentBottom = child.getBottom() + params.bottomMargin;
            int height = parentBottom - parentTop;

            int paddingVertical = Math.round((height - mIconSize) / 2);

            drawable.setBounds(parentLeft + mLeftPadding, parentTop + paddingVertical,
                    parentRight - mRightPadding, parentBottom - paddingVertical);
            drawable.draw(canvas);
    } else try {
        String link = findPlaceById(params.getPlaceId(),mStageList).getImg();
        Picasso.with(context).load(link).resize(150,150).into(new Target() {
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                drawable = new BitmapDrawable();
                parent.invalidate()
            }

            @Override
            public void onBitmapFailed(Drawable errorDrawable) {
            }

            @Override
            public void onPrepareLoad(Drawable placeHolderDrawable) {
            }
        });
    } catch (IndexOutOfBoundsException e) {
        Log.e(LOG_TAG, Log.getStackTraceString(e));
    }
}

修改:添加了工作代码。

private void drawStages(Canvas canvas, final RecyclerView parent) {
    final int parentLeft = parent.getPaddingLeft();
    final int parentRight = parentLeft + mLeftPadding + mIconSize + mRightPadding;

    int childCount = parent.getChildCount();
    for (int i = 0; i < childCount - 1; i++) {
        View child = parent.getChildAt(i);

        LineupLayoutManager.LayoutParams params =
                (LineupLayoutManager.LayoutParams) child.getLayoutParams();

        final int parentTop = child.getTop() + params.topMargin;
        final int parentBottom = child.getBottom() + params.bottomMargin;
        int height = parentBottom - parentTop;

        final int paddingVertical = Math.round((height - mIconSize) / 2);
        BitmapDrawable drawable;
        if(drawables.size()!=0)drawable = drawables.get(i);
        else drawable = null;
        if(drawable!=null){
            drawable.setBounds(parentLeft + mLeftPadding, parentTop + paddingVertical,
                    parentRight - mRightPadding, parentBottom - paddingVertical);
            drawable.draw(canvas);
        } else {
            String link = findPlaceById(params.getPlaceId(),mStageList).getImg();
            Picasso.with(context).load(link).resize(150,150).into(new Target() {
                @Override
                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                    BitmapDrawable d = new BitmapDrawable(context.getResources(),bitmap);
                    drawables.add(d);
                    parent.invalidateItemDecorations();
                }

                @Override
                public void onBitmapFailed(Drawable errorDrawable) {
                }

                @Override
                public void onPrepareLoad(Drawable placeHolderDrawable) {
                }
            });
        }
    }
}