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

时间:2015-07-10 13:19:25

标签: java android performance memory out-of-memory

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

建议的解决方案

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

    1. 在清单
    2. 中使堆大于true

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

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

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

      这是我的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;
      
          }
      
      
      } 
      

3 个答案:

答案 0 :(得分:6)

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

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

  3. 您应该将任何第三个ImageLoader用作具有一个LRU缓存+一个磁盘缓存的Singleton。你可以在这里找到一些好的(Any best third party tool to cache image in Android?

  4. 清单中的
  5. “largeHeap”根本不应该出现在你的脑海里。一旦你有泄漏,你就会有一个更大的堆来填补,直到OOM。

答案 1 :(得分:4)

哟可以删除内存缓存中的缓存图像。请使用MemoryCacheUtil

MemoryCacheUtils.removeFromCache(imageUrl, imageLoader.getMemoryCache());

DiscCacheUtils用于删除discCache

DiscCacheUtils.removeFromCache(url, ImageLoader.getInstance().getDiscCache());

此外,您可以使用以下方法清除内存缓存:

imageLoader.clearMemoryCache();

此外,您可以使用限制来控制内存和磁盘:

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())         
        .memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024)) 
        .discCache(new UnlimitedDiscCache(cacheDir)) 

答案 2 :(得分:1)

您可以尝试避免内存缓存,并限制磁盘缓存。要进一步优化,您可以查看the source