2016-03-19 4 views
0
  • у меня есть 2 разные ListView поданы с изображениями толькооптимизация памяти для статических изображений в ListView

  • Лучшим решением для оптимизации памяти для статических изображений в ListView

  • Я имею памяти выдавать каждый раз из выпуска памяти

  • Каждое решение в отношении динамических изображений или загрузка изображений с веб-сервиса

  • Что относительно статического изображения?

  • Я имею около 70-80 изображений в ListView (всего)

  • Код не требуется, так как я просто заполнение ListView с изображениями, не используется веб-сервис.

код:

private ListView lv; 

private ArrayList<Integer> cd; 
@Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_select); 


     lv = (ListView) findViewById(R.id.lv); 
     cd = new ArrayList<Integer>(); 

     cd1.add(R.drawable.fuld1); 
     cd1.add(R.drawable.ful2); 
     cd1.add(R.drawable.fu4); 




     lv.setAdapter(new Select(this, cd1)); 
     lv.setOnItemClickListener(this); 

    } 

адаптер Класс:

общественного класса SelectAdapter расширяет BaseAdapter {

private Activity activity; 
private LayoutInflater inflater; 
private ViewHolder holder; 
private ArrayList<Integer> list; 


public SelectAdapter(Activity activity, ArrayList<Integer> list) { 
    this.activity = activity; 
    inflater = (LayoutInflater) activity 
      .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    this.list = list; 
} 

@Override 
public int getCount() { 
    return 43; 
} 

@Override 
public Object getItem(int arg0) { 
    return arg0; 
} 

@Override 
public long getItemId(int arg0) { 
    return 0; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    if (convertView == null) { 
     convertView = inflater.inflate(R.layout.select_item, parent, 
       false); 
     holder = new ViewHolder(); 
     holder.iv = (ImageView) convertView 
       .findViewById(R.id.ivSelect; 

     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 


    holder.iv.setBackgroundResource(list.get(position)); 



    return convertView; 
} 

private class ViewHolder { 
    ImageView ivCard; 
} 


public static int calculateInSampleSize(
     BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 
    if (height > reqHeight || width > reqWidth) { 
     final int halfHeight = height/2; 
     final int halfWidth = width/2; 
     while ((halfHeight/inSampleSize) > reqHeight 
       && (halfWidth/inSampleSize) > reqWidth) { 
      inSampleSize *= 2; 
     } 
    } 
    return inSampleSize; 
} 

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
                int reqWidth, int reqHeight) { 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(res, resId, options); 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeResource(res, resId, options); 
} 

}

Log:

java.lang.OutOfMemoryError: Failed to allocate a 34560012 byte allocation with 4194304 free bytes and 14MB until OOM 
+0

кода того, что вы пытались до сих пор, был бы полезно –

ответ

1

Вам необходимо использовать BitmapFactory.Options. BitmapFactory.Options можно использовать для обработки размера Bitmap и других свойств без их загрузки в память с помощью inJustDecodeBounds. Чтобы удалить ошибку OutOfMemory, вам нужно загрузить уменьшенную версию Bitmap из ваших ресурсов (папка с возможностью выгрузки). Это можно сделать с помощью inSampleSize. Если inSampleSize> 1, он требует, чтобы декодер загрузил уменьшенную версию в память, избавив вас от ошибок OutOfMemory.

Пройдите через следующий веб-страницу для получения более подробной информации:

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

Демо-код:

Вам понадобится следующие два метода для обработки каждого растрового изображения или вытяжки файла:

public static int calculateInSampleSize(
     BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 
    if (height > reqHeight || width > reqWidth) { 
     final int halfHeight = height/2; 
     final int halfWidth = width/2; 
     while ((halfHeight/inSampleSize) > reqHeight 
       && (halfWidth/inSampleSize) > reqWidth) { 
      inSampleSize *= 2; 
     } 
    } 
    return inSampleSize; 
} 

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
                int reqWidth, int reqHeight) { 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(res, resId, options); 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeResource(res, resId, options); 
} 

Метод calculateInSampleSize используется для вычисления inSamp leSize для каждого растрового изображения. Полученное значение inSampleSize будет наилучшим подходящим значением или наилучшим образом подходит для масштабирования вашего растрового изображения к вашим указанным требованиям, как вы укажете с помощью аргументов одним и тем же методом.

Метод decodeSampleBitmapFromResource будет декодировать растровый файл из ресурсов вашего приложения и позволить вам рассчитать inSampleSize без выделения памяти для растрового изображения. Память для растрового изображения будет выделена только после того, как будет подсчитан правильный inSampleSize для этого конкретного растрового изображения. Это достигается с помощью свойства inJustDecodeBounds для объекта BitmapFactory.Options.

Теперь вам просто нужно использовать эти методы, чтобы добавить растровые изображения в список. Для примера предположим, что у вас есть ImageView в каждом элементе или строке вашего ListView. Теперь мы добавим растровое изображение в ImageView так:

imageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), 
      resID, imageView.getMaxWidth(), imageView.getMaxHeight())); 

Здесь, RESID будет идентификатор ресурса для Bitmap и для ширины и высоты я в настоящее время используется в ширину и высоту самого ImageView, потому что Я лично считаю это лучшим решением. Но вы можете использовать любое значение. Убедитесь, что ваше значение ширины и высоты не превышает ширину и высоту представления, на котором будет размещено растровое изображение.

Обновленный сегмент кода:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    if (convertView == null) { 
     convertView = inflater.inflate(R.layout.select_item, parent, 
       false); 
     holder = new ViewHolder(); 
     holder.ivCard = (ImageView) convertView 
       .findViewById(R.id.ivSelect); 
     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 


    holder.ivCard.setImageBitmap(decodeSampledBitmapFromResource(parent.getResources(), 
      list.get(position), holder.ivCard.getMaxWidth(), holder.ivCard.getMaxHeight())); 



    return convertView; 
} 

Посмотрите на последней строке метода GetView. ivCard - это ваш ImageView из вашего ViewHolder для вашего адаптера, который теперь будет использовать метод setImageBitmap, чтобы установить ресурс как растровое изображение в ImageView.

+0

может u вижу в этом коде что-то вроде этого ?????????????????????????????????? – tiger

+0

Я уже видел все такие вещи – tiger

+0

Нет, я не могу. Но вам нужно использовать методы inJustDecodeBounds и inSampleSize для эффективной загрузки растровых изображений. Загрузка растровых изображений напрямую без их масштабирования, безусловно, приведет к ошибкам OutOfMemory. –

1

При условии, что вы отображаете только 5-10 изображений на экране за раз, и каждое изображение составляет всего несколько сотен килобайтов в макс, при использовании обычного списка переработанного списка должно быть достаточно, чтобы избежать OOM.

добавить все ваши Drawable ресурс IdS к ListView первой

imageResList.add(R.drawable.fulllogocard1) 
imageResList.add(R.drawable.fulllogocard2) 
imageResList.add(R.drawable.fulllogocard3) 
imageResList.add(R.drawable.fulllogocard4) 
...... 

Затем реализовать свой адаптер следующим образом:

public ImageViewAdapter extends BaseAdapter 
{ 
    @Override 
    public int getCount() 
    { 
     return imageList.size(); 
    } 

    @Override 
    public Object getItem(int i) 
    { 
     return null; 
    } 

    @Override 
    public long getItemId(int i) 
    { 
     return 0; 
    } 

    @Override 
    public View getView(int i, View existingView, ViewGroup viewGroup) 
    { 
     if(existingView == null) 
     { 
      ImageView imageView = new ImageView(viewGroup.getContext()); 
      imageView.setImageResource(imageResList.get(i)); 
      return imageView; 
     } 
     else 
     { 
      ImageView imageView = ((ImageView) existingView); 
      imageView.setImageResource(imageResList.get(i)); 
      return imageView; 
     } 
    } 

} 

Адаптер просто перерабатывает существующие взгляды ListView, поэтому в любой заданной точке время на экране отображаются только видимые виды (и, следовательно, только видимые изображения).

Это всего лишь обходной путь/взлом. В идеале, вы хотели бы использовать библиотеку изображений, построенную для этой цели, таких как погрузчик универсального образа, скольжение, Picasso, или фреска

Picasso v/s Imageloader v/s Fresco vs Glide

Смежные вопросы