调用 BitmapDrawable.draw(Canvas canvas) 时应用崩溃

App crash when calling BitmapDrawable.draw(Canvas canvas)

我有这样的代码:

@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));
        }
    }
}

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

Fatal signal 11 (SIGSEGV), code 1, fault addr 0x58 in tid 17542

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

经过一些研究,我发现 Picasso 以某种方式干扰了 canvas。这意味着如果我将这些东西放在 picasso 方法之外,一切都会正常。

我现在只是假设,但您似乎在早些时候存储了对 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) {
                }
            });
        }
    }
}