加载大型位图

时间:2015-09-22 06:18:24

标签: android android-asynctask runnable android-bitmap

我有两个加载Bitmaps的方法。当我试图加载巨大的图像2000px x 6000px时,我已经UI冻结了大约3秒钟。 anubody可以帮助我提高巨大图像的加载速度吗?我对屏幕方向更改很重要,因为这些方法总是被lib调用,我的UI总是在旋转之前冻结约3秒......

    /**
     * Async task used to get image details
     */ 
    private static class TilesInitTask implements Runnable {
        private final WeakReference<ScaleImageView> viewRef;
        private final WeakReference<Context> contextRef;
        private final WeakReference<DecoderFactory<? extends ImageRegionDecoder>> decoderFactoryRef;
        private final Uri source;
        private ImageRegionDecoder decoder;
        private Exception exception;

        public TilesInitTask(ScaleImageView view, Context context, DecoderFactory<? extends ImageRegionDecoder> decoderFactory, Uri source) {
            this.viewRef = new WeakReference<>(view);
            this.contextRef = new WeakReference<>(context);
            this.decoderFactoryRef = new WeakReference<DecoderFactory<? extends ImageRegionDecoder>>(decoderFactory);
            this.source = source;
        }

        public void run() {
            ScaleImageView view = null;
            try {
                String sourceUri = source.toString();
                Context context = contextRef.get();
                DecoderFactory<? extends ImageRegionDecoder> decoderFactory = decoderFactoryRef.get();
                view = viewRef.get();
                if (context != null && decoderFactory != null && view != null) {
                    decoder = decoderFactory.make();
                    Point dimensions = decoder.init(context, source);
                    int sWidth = dimensions.x;
                    int sHeight = dimensions.y;

                    int exifOrientation = view.getExifOrientation(sourceUri);
                    if (view.sRegion != null) {
                        sWidth = view.sRegion.width();
                        sHeight = view.sRegion.height();
                    }
                    view.onTilesInited(decoder, sWidth, sHeight, exifOrientation);
                }
            } catch (Exception e) {
                Log.e(TAG, "Failed to initialise bitmap decoder", e);
                this.exception = e;
                if (view != null && view.onImageEventListener != null) {
                    view.onImageEventListener.onImageLoadError(exception);
                }
            }
        }
    }

    /**
     * Called by worker task when decoder is ready and image size and EXIF orientation is known.
     */
    private synchronized void onTilesInited(ImageRegionDecoder decoder, int sWidth, int sHeight, int sOrientation) {
        // If actual dimensions don't match the declared size, reset everything.
        if (this.sWidth > 0 && this.sHeight > 0 && (this.sWidth != sWidth || this.sHeight != sHeight)) {
            reset(false);
            if (bitmap != null) {
                if (!bitmapIsCached) {
                    bitmap.recycle();
                }
                bitmap = null;
                bitmapIsPreview = false;
                bitmapIsCached = false;
            }
        }
        this.decoder = decoder;
        this.sWidth = sWidth;
        this.sHeight = sHeight;
        this.sOrientation = sOrientation;
        checkReady();
        checkImageLoaded();
        invalidate();
        requestLayout();
    }
    /**
     * Async task used to load images
     */
    private static class TileLoadTask implements Runnable {
        private final WeakReference<ScaleImageView> viewRef;
        private final WeakReference<ImageRegionDecoder> decoderRef;
        private final WeakReference<Tile> tileRef;
        private Exception exception;

        public TileLoadTask(ScaleImageView view, ImageRegionDecoder decoder, Tile tile) {
            this.viewRef = new WeakReference<>(view);
            this.decoderRef = new WeakReference<>(decoder);
            this.tileRef = new WeakReference<>(tile);
            tile.loading = true;
        }

        public void run() {
            ScaleImageView view = null;
            try {
                view = viewRef.get();
                ImageRegionDecoder decoder = decoderRef.get();
                Tile tile = tileRef.get();
                if (decoder != null && tile != null && view != null && decoder.isReady()) {
                    synchronized (view.decoderLock) {
                        // Update tile's file sRect according to rotation
                        view.fileSRect(tile.sRect, tile.fileSRect);
                        if (view.sRegion != null) {
                            tile.fileSRect.offset(view.sRegion.left, view.sRegion.top);
                        }
                        tile.bitmap = decoder.decodeRegion(tile.fileSRect, tile.sampleSize);
                        tile.loading = false;
                        view.onTileLoaded();
                    }
                } else if (tile != null) {
                    tile.loading = false;
                }
            } catch (Exception e) {
                Log.e(TAG, "Failed to decode tile", e);
                this.exception = e;
                if (view != null && view.onImageEventListener != null) {
                    view.onImageEventListener.onTileLoadError(exception);
                }
            }
        }
    }

    /**
     * Called by worker task when a tile has loaded. Redraws the view.
     */
    private synchronized void onTileLoaded() {
        checkReady();
        checkImageLoaded();
        if (isBaseLayerReady() && bitmap != null) {
            if (!bitmapIsCached) {
                bitmap.recycle();
            }
            bitmap = null;
            bitmapIsPreview = false;
            bitmapIsCached = false;
        }
        invalidate();
    }

1 个答案:

答案 0 :(得分:-1)

使用位图和图片是一项敏感操作。我建议您使用库来进行这类操作

https://github.com/nostra13/Android-Universal-Image-Loader

http://square.github.io/picasso/

编辑:

您可以在这里添加和初始化库。 Correct usage of Universal Image Loader

使用最佳配置初始化后,您可以使用适合您的操作的文件路径:

"http://example.com/image.png" // from Web
"file:///mnt/sdcard/image.png" // from SD card
"file:///mnt/sdcard/video.mp4" // from SD card (video thumbnail)
"content://media/external/images/media/13" // from content provider
"content://media/external/video/media/13" // from content provider (video thumbnail)
"assets://image.png" // from assets
"drawable://" + R.drawable.img // from drawables (non-9patch images)

最后你可以加载它:

ImageLoader imageLoader = ImageLoader.getInstance(); // Get singleton instance
imageLoader.displayImage(imageUri, imageView);
祝你好运。