如何在Android中使用ImageLoader的释放位图的内存?位图、内存、如何在、ImageLoader

2023-09-06 02:08:52 作者:丟三丟四不丟你〆

我加载图像到从服务器的网格视图。对于这一点,我使用的是通用的图像加载器。我现在用的图像加载器适配器的getview()方法中。它从ArrayList中与放图片的URL;装载来自服务器的图像。图像可以在100的。我在显示的片段网格视图,以便为每个片段有一个单独的网格视图。当我多个片段之间切换很长一段时间我不再让内存不足的错误。

建议的解决方案

在释放未使用的位图。

所以,我加载使用第三方库的图像。我只是路过图像视图中调用函数,我怎么能释放位图?

请堆真正的大清单中

我想堆内存是动态和放大器;每当有增加的内存垃圾收集器将释放内存。

3.使用 UIL /毕加索/滑翔,以避免内存泄漏

4 code发布片段的onDestroy()方法()

的记忆

 私人无效unbindDrawables(查看视图)
{
        如果(view.getBackground()!= NULL)
        {
                view.getBackground()setCallback(空)。
        }
        如果(查看的instanceof的ViewGroup和放大器;&安培;!(查看的instanceof适配器视图))
        {
                的for(int i = 0;我≤((ViewGroup中)查看).getChildCount();我++)
                {
                        unbindDrawables(((ViewGroup中)查看).getChildAt(一));
                }
                ((ViewGroup中)查看).removeAllViews();
        }
}
 

我已经使用第三方库。

下面是code我gridViewAdapter类。

  @覆盖
    公共查看getView(INT位置,查看convertView,ViewGroup中父){
        最后ViewHolder持有人;
        查看查看= convertView;
        如果(查看== NULL)
        {
            鉴于= inflater.inflate(R.layout.grid_item_photo,父母,假);
            持有人=新ViewHolder();
            holder.imageView =(ImageView的)view.findViewById(R.id.imgLoader);
            holder.play =(ImageView的)view.findViewById(R.id.play);


            view.setTag(保持器);
        }
        其他
        {
            支架=(ViewHolder)view.getTag();
        }
        尝试{
        如果(IMAGES_LIST.get(位置).getType()。等于(视频))
        {
        holder.play.setVisibility(View.VISIBLE);
        }
         其他
        {
         holder.play.setVisibility(View.GONE);

         }
        ImageLoader.getInstance().displayImage(AppConst.BASE_IMAGE_URL+IMAGES_LIST.get(position).getThumbnail(), holder.imageView,期权,新SimpleImageLoadingListener(){
                    @覆盖
                    公共无效onLoadingStarted(字符串imageUri,查看查看){
                        view.setClickable(真正的);
                    }

                    @覆盖
                    公共无效onLoadingFailed(字符串imageUri,视图中查看,FailReason failReason){
                        view.setClickable(真正的);

                    }

                    @覆盖
                    公共无效onLoadingComplete(字符串imageUri,查看视图,位图loadedImage){
                        view.setClickable(假);

                    }
                },新ImageLoadingProgressListener(){
                    @覆盖
                    公共无效onProgressUpdate(字符串imageUri,视图中查看,INT目前,诠释总计){

                    }
                });
        }赶上(例外五)
        {

        }
        赶上(OutOfMemoryError异常E)
        {

        }
        返回查看;
    }
    静态类ViewHolder {
        ImageView的ImageView的,打;

    }


}
 
热修复之Tinker的集成与使用方法

解决方案

这听起来像你的碎片漏 - 你的片段保留在内存中所有的内容(包括位图)即使的onDestroy被调用。您可以使用MAT +堆转储看看到底是什么导致泄漏(有很多导游可在那里)​​。第一个犯罪嫌疑人应该是出片段类的你这个从你的片段通过单身。作为第一步,我会清理一切从您的onDestroy片段。

请在SimpleImageLoadingListener()保存您的片段作为WeakReference的内部静态类 - 这将可能减少泄漏(或其中的至少一个)

您应该使用任何第三ImageLoader的作为一个Singleton一个LRU缓存+一个磁盘缓存。你可以找到一些好的位置(Any最好的第三方工具来缓存图像中的Andr​​oid?)

在清单largeHeap不应该在你的心中的。一旦你有一个泄漏,那么你只会有一个更大的堆来填补,直到OOM。

I am loading images into a grid view from a server. For this, I'm using Universal Image loader. I am using the image loader inside the getview() method of the adapter. It takes the URL of the image from arraylist & loads the image from server. Images can be in 100's. I am displaying the grid view in a fragment so for each fragment there is a separate grid view. When I switch between multiple fragments for a long time I no longer get the out of memory error.

Suggested solution:

Release the unused bitmap.

So I am loading the images using third party library. I am just passing the image view in the calling function so how can I release the bitmap?

Make heap large true in manifest

I guess heap memory is dynamic & whenever there is an increase in memory garbage collector will free the memory.

3.Use UIL/Picasso/Glide to avoid memory leaks

4.Code to release the memory of fragment onDestroy() method ()

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();
        }
} 

I am already using a third party library.

Here is the code for my gridViewAdapter class.

@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;

    }


} 

解决方案

It sounds like your fragments leak - your fragment stays in memory with all their content (including the bitmap) even if onDestroy is called. You can use MAT + Heap dumps the see what exactly causes the leak (there are many guides available out there). The first suspects should be Singletons of out of fragment classes that you pass "this" from your fragments. As the first step I would clear everything from your fragment in onDestroy.

Make the "SimpleImageLoadingListener()" an inner static class that holds your fragment as WeakReference - this will probably reduce the leak (or at least one of them).

You should be using any 3rd ImageLoader as a Singleton with one LRU cache + one disk cache. You can find some good ones here (Any best third party tool to cache image in Android?)

"largeHeap" in the manifest shouldn't be on your mind at all. Once you have a leak then you'll just have a larger heap to fill up until OOM.