调用 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) {
}
});
}
}
}
我有这样的代码:
@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) {
}
});
}
}
}