Как выпустить память растрового изображения с помощью imageloader в Android?

Я загружаю изображения в виде сетки с сервера. Для этого я использую загрузчик Universal Image. Я использую загрузчик изображений внутри метода getview() адаптера. Он берет URL-адрес изображения из arraylist и загружает изображение с сервера. Изображения могут быть в 100-х годах. Я показываю вид сетки в фрагменте, поэтому для каждого фрагмента есть отдельный вид сетки. Когда я переключаюсь между несколькими фрагментами в течение длительного времени, я больше не получаю ошибку из памяти.

Рекомендуемое решение:

  • Отпустите неиспользуемое растровое изображение.

Итак, я загружаю изображения, используя стороннюю библиотеку. Я просто передаю изображение в вызывающей функции, так как я могу освободить растровое изображение?

  1. Сделать кучу большой истиной в манифесте

Я думаю, что куча памяти динамична, и всякий раз, когда происходит увеличение памяти, сборщик мусора освобождает память.

3.Use UIL/Picasso/Glide, чтобы избежать утечек памяти

4.Code, чтобы освободить память фрагмента 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();
        }
} 

Я уже использую стороннюю библиотеку.

Вот код для моего класса 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;

    }


} 

Ответ 1

  • Похоже на утечку фрагментов - ваш фрагмент остается в памяти со всем содержимым (включая растровое изображение), даже если вызывается onDestroy. Вы можете использовать MAT + Heap dumps, чтобы увидеть, что именно вызывает утечку (там доступно множество руководств). Первыми подозреваемыми должны быть Singletons из классов фрагментов, которые вы передаете "this" из ваших фрагментов. В качестве первого шага я очистил все от вашего фрагмента в onDestroy.

  • Сделайте "SimpleImageLoadingListener()" внутренним статическим классом, который содержит ваш фрагмент как WeakReference - это, вероятно, уменьшит утечку (или, по крайней мере, один из них).

  • Вы должны использовать любой третий ImageLoader в качестве Singleton с одним кешем LRU и одним дисковым кэшем. Здесь вы можете найти несколько хороших (любой лучший сторонний инструмент для кеширования изображения на Android?)

  • "largeHeap" в манифесте не должно быть в вашем уме. Как только у вас будет утечка, вы просто получите большую кучу, чтобы заполнить ее до OOM.

Ответ 2

Yo может удалять кэшированное изображение в кеше памяти. Используйте 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)) 

Ответ 3

Может быть, причина в том, что вы просто используете 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();

Ответ 4

Вы можете попытаться избежать кеша памяти и ограничить кеш диска. Для дальнейших оптимизаций вы можете проверить источник.