在CircularImageView中加载图像时出现内存不足错误

时间:2016-04-14 07:47:26

标签: android imageview out-of-memory

我正在尝试在CircularImageView中加载图像,但它给了我outOfMemory错误。 我正在使用以下代码进行CircularImageView:

CircularImageView.java

    public class CircularImageView extends ImageView {

    public CircularImageView(Context ctx, AttributeSet attrs) {
        super(ctx, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        Drawable drawable = getDrawable();

        if (drawable == null) {
            return;
        }

        if (getWidth() == 0 || getHeight() == 0) {
            return;
        }
        Bitmap b = ((BitmapDrawable) drawable).getBitmap();
        Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

        int w = getWidth(), h = getHeight();

        Bitmap roundBitmap = getRoundedCroppedBitmap(bitmap, w);
        canvas.drawBitmap(roundBitmap, 0, 0, null);

    }

    public static Bitmap getRoundedCroppedBitmap(Bitmap bitmap, int radius) {
        Bitmap
                finalBitmap;
        if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
            finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
                    false);
        else
            finalBitmap = bitmap;
        Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
                finalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
                finalBitmap.getHeight());

        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(Color.parseColor("#BAB399"));
        canvas.drawCircle(finalBitmap.getWidth() / 2 + 0.7f,
                finalBitmap.getHeight() / 2 + 0.7f,
                finalBitmap.getWidth() / 2 + 0.1f, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(finalBitmap, rect, rect, paint);

        return output;
    }

}

我在设计中使用它如下:

 <com.almabay.almachat.circularImageView.CircularImageView
    android:id="@+id/img_group"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:layout_alignParentLeft="true" />

我从服务器获取图像并尝试使用Adapter在列表视图中显示它。此处使用了以下代码:

Picasso.with(context).load(image_url).error(R.drawable.default_avatar).into(viewHolder.imgGroup);

此处image_url是要在圆形图像视图中加载的图像的URL .ViewHolder.imgGroup是circularImageView。

请帮我解决问题。

2 个答案:

答案 0 :(得分:2)

我看到你正在使用Picasso进行图像加载,为什么不使用毕加索图像变换。它实现起来非常简单: -

ImageView im = (ImageView) findViewById(R.id.img1);

    Picasso.with(MainActivity2.this).load(R.drawable.kitten)
            .transform(new CropCircleTransformation()).into(im);

它看起来像这个

enter image description here

您只需要添加转换类

import com.squareup.picasso.Transformation;

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;

public class CropCircleTransformation implements Transformation {

  @Override public Bitmap transform(Bitmap source) {
    int size = Math.min(source.getWidth(), source.getHeight());

    int width = (source.getWidth() - size) / 2;
    int height = (source.getHeight() - size) / 2;

    Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(bitmap);
    Paint paint = new Paint();
    BitmapShader shader =
        new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
    if (width != 0 || height != 0) {
      // source isn't square, move viewport to center
      Matrix matrix = new Matrix();
      matrix.setTranslate(-width, -height);
      shader.setLocalMatrix(matrix);
    }
    paint.setShader(shader);
    paint.setAntiAlias(true);

    float r = size / 2f;
    canvas.drawCircle(r, r, r, paint);

    source.recycle();

    return bitmap;
  }

  @Override public String key() {
    return "CropCircleTransformation()";
  }
}

我们可以在此处找到更多转化https://github.com/wasabeef/picasso-transformations

答案 1 :(得分:1)

通常情况下,我会告诉您错误可能在任何地方,您可能正在泄漏。但是你在onDraw中制作了2个新的位图?所有3个都在记忆中?这不仅非常浪费,而且你的表现很糟糕 - 你甚至应该避免在onDraw中使用new,更不用说分配位图了。

把它扔出去并完全重写。你应该避免在这里使用drawable(特别是因为你无论如何都假设它是一个位图,这是一个坏主意),你应该接受位图的文件名或资源id并在其中读取/使用1 createBitmap进行缩放使用BitmapOptions命令。您应该在设置位图时执行此操作并保存结果,不要在始终调用的onDraw中进行缩放。您可以通过使用圆形剪切路径而不是使用porter duff模式和第二个画布来避免第3个位图。你可以用1位图完成所有这些,并且应该。