android - 如何传递位图参数?

标签 android bitmap

我想从我的 SD 卡加载一些图像并将它们设置为我的应用程序布局的背景。我想高效地执行此操作,这样我就不会出现 OutOfMemory Exception 并在后台执行此操作。所以我已经阅读并使用了关于在 Processing Bitmaps 中处理位图的几乎完全相同的代码。 在安卓开发者。这是我的代码:

public class ImageLoader {

    private final Context context;
    private int imageWidth;
    private int imageHeight;

    public ImageLoader(Context context, int imageWidth, int imageHeight) {

        this.context = context;
        setImageSize(imageWidth, imageHeight);
    }

    public ImageLoader(Context context, int imageSize) {

        this.context = context;
        setImageSize(imageSize);
    }

    public void setImageSize(int width, int height) {
        imageWidth = width;
        imageHeight = height;
    }

    public void setImageSize(int size) {
        setImageSize(size, size);
    }

    public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {

        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;

        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

    public static Bitmap decodeSampleBitmapFromResource(Resources res, int resId,
            int reqWidth, int reqHeight) {

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }

    public static boolean cancelPotentialWork(int data, ImageView imageView) {

        final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);

        if (bitmapWorkerTask != null) {

            final int bitmapData = bitmapWorkerTask.data;

            if (bitmapData != data) {

                // Cancel previous task
                bitmapWorkerTask.cancel(true);

            } else {
                // The same work is already in progress
                return false;
            }
        }

        // No task associated with the ImageView, or an existing task was cancelled
        return true;
    }

    private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {

        if (imageView != null) {

            final Drawable drawable = imageView.getDrawable();

            if (drawable instanceof AsyncDrawable) {

                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;

                return asyncDrawable.getBitmapWorkerTask();
            }
        }

        return null;
    }

    public void loadBitmap(int resId, ImageView imageView) {

        if (cancelPotentialWork(resId, imageView)) {

            final BitmapWorkerTask task = new BitmapWorkerTask(imageView);

            final AsyncDrawable asyncDrawable =
                    new AsyncDrawable(context.getResources(), ???mPlaceHoderBitmap???, task);

            imageView.setImageDrawable(asyncDrawable);

            task.execute(resId);
        }
    }

    class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {

        private final WeakReference<ImageView> imageViewReference;
        private int data = 0;

        public BitmapWorkerTask(ImageView imageView) {

            // Use a WeakReference to ensure the ImageView can be garbage collected
            imageViewReference = new WeakReference<ImageView>(imageView);
        }

        // Decode image in background
        @Override
        protected Bitmap doInBackground(Integer... params) {

            data = params[0];
            return decodeSampleBitmapFromResource(context.getResources(), data, imageWidth, imageHeight);
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {

            if (isCancelled()) {
                bitmap = null;
            }

            if (imageViewReference != null && bitmap != null) {

                final ImageView imageView = imageViewReference.get();

                final BitmapWorkerTask bitmapWorkerTask =
                        getBitmapWorkerTask(imageView);

                if (this == bitmapWorkerTask && imageView != null) {

                    imageView.setImageBitmap(bitmap);
                }
            }
        }

    }

    static class AsyncDrawable extends BitmapDrawable {

        private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;

        public AsyncDrawable(Resources res, Bitmap bitmap,
                BitmapWorkerTask bitmapWorkerTask) {

            super(res, bitmap);

            bitmapWorkerTaskReference = 
                    new WeakReference<ImageLoader.BitmapWorkerTask>(bitmapWorkerTask);
        }

        public BitmapWorkerTask getBitmapWorkerTask() {

            return bitmapWorkerTaskReference.get();
        }
    }
}

但是在 loadBitmap(int resId, Bitmap bitmap, ImageView imageView) 方法中我不知道如何传递位图。如果我使用 BitmapFactory.decode* 我可能会遇到异常。我应该如何为我的图像数据源传递位图参数?

最佳答案

在那篇文章中:

public void loadBitmap(int resId, ImageView imageView) {
    if (cancelPotentialWork(resId, imageView)) {
        final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
        final AsyncDrawable asyncDrawable =
                new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);
        imageView.setImageDrawable(asyncDrawable);
        task.execute(resId);
    }
}

您传递给 AsyncDrawable 的位图应该是加载实际图像时的占位符。

因此您可以对占位符图像进行一次解码,然后将其传递。

在Activity中创建一个Bitmap对象:

Bitmap placeHolder=null;

并且在onCreate

placeHolder=BitmapFactory.decodeResource(getResources(), R.drawable.place_holder);

现在每次你想从 SD 卡调用加载一些图像时:

loadBitmap(<resId>,placeHolder,imageView);

关于android - 如何传递位图参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21142174/

相关文章:

java - 让多个联系人显示在我的应用程序中有点困难。

android - 使用 drawBitmap 缩放位图

android - 为什么 BitmapFactory.decodeResource 会缩放我的图像?

c - 如何释放从 GdipCreateBitmapFromHBITMAP 创建的对象?

iphone - 是否可以将多个纹理映射到 openGL ES 中的一个形状上?

Android DevicePolicyManager 启用人脸解锁

android - 如何制作另一个文本 block ?

java - 需要帮助随机化图像并且不要在整个 Activity 中重复

c++ - 从内存中获取 jpeg 的大小(使用 GDI++ 转换)

java - 在 ImageView(?) 中操作照片,然后返回该图片