如何实现图库(本地图片)

时间:2012-03-20 12:21:24

标签: android android-viewpager out-of-memory gallery android-gallery

目前即时制作应用程序以显示SD卡中的图像。基本上你可以制作一张相册并添加图片,无论是来自MediaStore选择器的相机。

我尝试了两种方法:

  1. 带有自定义BaseAdapter的标准图库应用,可返回视图
  2. 具有自定义PagerAdapter
  3. 的viewpager

    我不想显示网格视图,所以它应该立即全屏显示。之后我想禁用向左和向右滑动,只听取点击次数。

    Atm这两种方法都在纵向模式下工作。当我切换到横向时,一些图像就会掉落

    03-20 12:20:56.515: W/OpenGLRenderer(17398): Bitmap too large to be uploaded into a texture
    

    后面是内存不足错误。堆栈溢出如果满了OOM和库的问题,你应该回收视图使它们工作,因为convertView在来自BaseAdapter的getView中总是为空。

    所以我使用了回收器来查看视图,我将其限制为2个视图,并且纵向模式适用于方法1(使用图库)。景观仍然给我同样的问题。

    对于方法2(viewflipper),它通过

    处理视图
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
    

    从未被称为btw ...但肖像模式在这里工作。景观仍然崩溃。

    我获取位图的方法:

    public static Bitmap getBitmap(Context ctx, int imageId, ImageView target) {
    
        String file = getPath(ctx, imageId);
    
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;
    
        BitmapFactory.decodeFile(file, bmOptions);
        WindowManager mgr = (WindowManager)         ctx.getSystemService(Context.WINDOW_SERVICE);
    
        int scaleFactor = 1;
    
        if (mgr != null) {
            // Get the dimensions of the View
            int targetW = mgr.getDefaultDisplay().getWidth();
            int targetH = mgr.getDefaultDisplay().getHeight();
            Log.d(TAG, "Image width + height=" + targetW + "," + targetH);
    
    
            int photoW = bmOptions.outWidth;
            int photoH = bmOptions.outHeight;
            // Determine how much to scale down the image
            scaleFactor = Math.min(photoW / targetW, photoH / targetH);
    
        } else {
            Log.d(TAG, "Target is null");
        }
    
        // Get the dimensions of the bitmap
        // Decode the image file into a Bitmap sized to fill the View
        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;
        bmOptions.inPurgeable = true;
        logHeap(ImageHelper.class);
    
        Bitmap bm = BitmapFactory.decodeFile(file, bmOptions);
    
        if (target != null) {
            target.setImageBitmap(bm);
        }
        return bm;
    }
    

    工作正常,我知道我使用窗口管理器来获取屏幕大小,但这是因为当我给它充气时,我的ImageView仍然是大小(0,0)。之后我打电话给

    imgView.setLayoutParams(new Gallery.LayoutParams(
                Gallery.LayoutParams.FILL_PARENT,
                Gallery.LayoutParams.FILL_PARENT));
        imgView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
    

    似乎没什么用......

    请注意,我不使用APK中包含的drawable或任何其他资源。 这个画廊应该能够从SD卡或相机中加载任何质量的图片。很明显,画廊应该能够处理目录中的图像。

    有人可以帮我解决以下问题吗?

    1. 有没有办法让默认的Gallery立即全屏显示并阻挡网格视图?这样我只需要一个适配器来提供图像而不是自己创建视图。 (也许这解决了OOM崩溃问题)
    2. 我的Bitmap解码功能好吗?我是否需要建立一些黑客来捕捉景观变化?
    3. 使用viewpager或画廊制作我需要的画廊的最佳方式是什么?
    4. 有没有人有一些不会崩溃的全屏图库示例代码?

1 个答案:

答案 0 :(得分:1)

这是我过去曾经遇到过几次的问题。 Google实际上发布了一篇关于此的文章。

问题在于用于解码图像的inSampleSize。由于不同的设备具有不同的屏幕和内存大小(VM堆大小可能从12到64或更多Mb),因此您无法以相同的方式对所有图像进行解码。例如,具有12Mb堆内存的320x240设备中的图像应该是inSampleSize,而1280x720 64Mb堆内存设备应该使用另一个inSampleSize(更大的一个)。

我攻击的文章显示了一种有效的方法来渲染给定高度和宽度的图像。特别注意最后一个代码段,它们“预先打开”文件并计算inSampleSize以便稍后进行“完全解码”。

我还想补充一下这些建议。

  1. 以异步方式使用“getBitmap”函数,调用新线程或asyncTask(这样做是因为使用SD需要时间,这会导致应用程序挂起,变慢并导致错误对中低端设备的印象。

  2. 尝试始终使用相同的Bitmap对象。避免创建多个“Bitmap bitmap = new Bitmap()”。您必须意识到加载的位图存储在ram中,一旦分配给视图,垃圾收集器就越难以获取它们。

  3. 完成使用Bitmap后,将其设为null。这样,想象你有12Mb最大堆RAM。你的应用现在正在使用8Mb。垃圾收集器启动并且无法获得更多未使用的RAM。在将数据分配给ImageView并以某种方式保留其引用之后,10位图快速永远不会使它们为空。假设每个位图占用500Kb的Ram你的应用程序将崩溃。使用后始终使位图为空。

  4. 最后使用google platform-tools中提供的DDMS(你可以通过eclipse访问它来调试并查看你的内存使用情况,你也可以强制垃圾收集来查看你的应用程序的行为)。