如何在android中使用imageloader释放位图的内存?

Tec*_*ain 12 java memory performance android out-of-memory

我正在从服务器将图像加载到网格视图中.为此,我正在使用通用图像加载器.我在适配器的getview()方法中使用图像加载器.它从arraylist获取图像的URL并从服务器加载图像.图像可以是100年代.我正在片段中显示网格视图,因此对于每个片段,都有一个单独的网格视图.当我长时间在多个片段之间切换时,我不再出现内存不足错误.

建议的解决方案:

  1. 释放未使用的位图.

所以我使用第三方库加载图像.我只是在调用函数中传递图像视图,那么如何释放位图?

  1. 在清单中使堆大为真

我猜堆内存是动态的,每当内存增加时,垃圾收集器就会释放内存.

3.使用UIL/Picasso/Glide以避免内存泄漏

4.Code释放片段onDestroy()方法的内存()

private void unbindDrawables(View view)
{
        if (view.getBackground() != null)
        {
                view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup && !(view instanceof AdapterView))
        {
                for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++)
                {
                        unbindDrawables(((ViewGroup) view).getChildAt(i));
                }
                ((ViewGroup) view).removeAllViews();
        }
} 
Run Code Online (Sandbox Code Playgroud)

我已经在使用第三方库了.

这是我的gridViewAdapter类的代码.

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        View view = convertView;
        if (view == null)
        {
            view = inflater.inflate(R.layout.grid_item_photo, parent, false);
            holder = new ViewHolder();
            holder.imageView = (ImageView) view.findViewById(R.id.imgLoader);
            holder.play = (ImageView) view.findViewById(R.id.play);


            view.setTag(holder);
        } 
        else 
        {
            holder = (ViewHolder) view.getTag();
        }
        try{
        if(IMAGES_LIST.get(position).getType().equals("video"))
        {
        holder.play.setVisibility(View.VISIBLE);
        }
         else
        {
         holder.play.setVisibility(View.GONE);

         }
        ImageLoader.getInstance().displayImage(AppConst.BASE_IMAGE_URL+IMAGES_LIST.get(position).getThumbnail(), holder.imageView, options, new SimpleImageLoadingListener() {
                    @Override
                    public void onLoadingStarted(String imageUri, View view) {
                        view.setClickable(true);
                    }

                    @Override
                    public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
                        view.setClickable(true);

                    }

                    @Override
                    public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                        view.setClickable(false);

                    }
                }, new ImageLoadingProgressListener() {
                    @Override
                    public void onProgressUpdate(String imageUri, View view, int current, int total) {

                    }
                });
        }catch(Exception e)
        {

        }
        catch(OutOfMemoryError e)
        {

        }
        return view;
    }
    static class ViewHolder {
        ImageView imageView,play;

    }


} 
Run Code Online (Sandbox Code Playgroud)

Mar*_*rky 6

  1. 这听起来像你的片段泄漏 - 即使调用了onDestroy,你的片段也会在所有内容(包括位图)中保留在内存中.您可以使用MAT + Heap转储查看确切导致泄漏的原因(那里有许多指南).第一个嫌疑人应该是片段类中的单例,你可以从你的片段传递"this".作为第一步,我将从onDestroy中的片段中清除所有内容.

  2. 使"SimpleImageLoadingListener()"成为一个内部静态类,将您的片段保存为WeakReference - 这可能会减少泄漏(或至少其中一个).

  3. 您应该将任何第三个ImageLoader用作具有一个LRU缓存+一个磁盘缓存的Singleton.你可以在这里找到一些好的(任何最好的第三方工具来缓存Android中的图像?)

  4. 清单中的"largeHeap"根本不应该出现在你的脑海里.一旦你有泄漏,那么你将只有一个更大的堆来填补,直到OOM.


Vis*_*hwa 0

可能的原因是你只是ImageLoader通过创建它的实例来使用它,而且我不知道DisplayImageOptions你有什么。尝试更改选项设置并检查它。对我来说,这个选项帮助我在List.

在您的应用程序中尝试此选项。

DisplayImageOptions imageOptions = new DisplayImageOptions.Builder().showImageForEmptyUri(R.drawable.ic_launcher).showImageOnFail(R.drawable.ic_launcher).resetViewBeforeLoading(true).cacheOnDisk(true).imageScaleType(ImageScaleType.EXACTLY).bitmapConfig(Bitmap.Config.RGB_565).considerExifParams(true).displayer(new FadeInBitmapDisplayer(3000, true, true, false)).build();
Run Code Online (Sandbox Code Playgroud)