1

В нашем приложении Android у нас есть ListView, заполненный активными чатами между разными пользователями. Нет никакого реального ограничения количества активных чатов, которые пользователь может иметь, поэтому, очевидно, нет ограничений на количество элементов, которые содержит этот список.Производительность Android ListView

Каждый элемент ListView состоит из:

  • 1x завышены Посмотреть проведение нескольких изображений
  • 1x ImageView
  • 1x Строка

Все работает так, как мы хотим, чтобы с точки зрения времени загрузки и с точки зрения внешнего вида и состава. Хотя ListView содержит элементы ниже 20-иш, все в порядке. Как только ListView начнет содержать выше этих 20-ишных элементов, производительность постепенно становится все более невыносимой для каждого добавленного элемента.

Я делал некоторые пробы и ошибки тестирования, пытаясь отключить каждый элемент и компонент структуры элемента, и то, что я обнаружил, что падение производительности происходит всякий раз, когда мы имеем любого вида изображения в предметах. Так что независимо от того, какой тип, любой образ заставляет производительность сосать, когда ListView содержит более 20-иш-элементов. Как я могу это оптимизировать? Я добавил getView из нашего адаптера + наш метод для добавления фотографий.

Любые и все справки и/или предложения приветствуются :)

GetView от нашего адаптера:

public View getView(int position, View convertView, ViewGroup parent) { 
    System.out.println("getview:"+position+" "+convertView); 

    ViewHolder viewHolder; 

    Match match = matches.get(position); 

    if(convertView==null){ 
     LayoutInflater inflater = (LayoutInflater) mContext 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     convertView = inflater.inflate(R.layout.matches_list_item, parent, false); 

     viewHolder = initViewHolder(convertView, match); 

    } else { 

     viewHolder = (ViewHolder) convertView.getTag(); 
    } 

    addGroupPhoto(imageSize, match, viewHolder, false); 

    if (match.matchedGroup != null) { 

     viewHolder.names.setText(match.matchedGroup.getMembersNames()); 
     viewHolder.matchedText.setText(match.latestMessage.value == null ? 
       String.format(mContext.getString(R.string.matched_on), getFormatedMatchDate(match.matchedOn)) : match.latestMessage.value); 

    } 
    return convertView; 
} 

addGroupPhoto от нашего адаптера

private void addGroupPhoto(int imageSize, Match match, ViewHolder viewHolder,  boolean isSelected) { 

    if (viewHolder.groupPhoto.findViewById(R.id.unseen_messages) != null) { 
     viewHolder.groupPhoto.removeView(viewHolder.groupPhoto.findViewById(R.id.unseen_messages)); 
    } 

    if (match.matchedGroup != null) { 
     RelativeLayout lay = Utilities.createGroupImagePhoto(mContext, imageSize, imageSize, match.matchedGroup.members, Utilities.GROUP_PHOTO_MODE_GROUP_WITHOUT_NAMES); 
     ((RelativeLayout.LayoutParams)lay.getLayoutParams()).addRule(RelativeLayout.CENTER_VERTICAL); 
     ((RelativeLayout.LayoutParams)lay.getLayoutParams()).addRule(RelativeLayout.ALIGN_LEFT); 
     ((RelativeLayout.LayoutParams)lay.getLayoutParams()).setMargins(smallMargin, 0, 0, 0); 
     viewHolder.groupPhoto.addView(lay); 
     lay.invalidate(); 
    } 

    ImageView crop = new ImageView(mContext); 
    crop.setBackgroundResource(getCropImageDrawable(isSelected)); 
    crop.setLayoutParams(new RelativeLayout.LayoutParams(imageSize,imageSize)); 
    ((RelativeLayout.LayoutParams)crop.getLayoutParams()).addRule(RelativeLayout.CENTER_VERTICAL); 
    ((RelativeLayout.LayoutParams)crop.getLayoutParams()).addRule(RelativeLayout.ALIGN_LEFT); 
    ((RelativeLayout.LayoutParams)crop.getLayoutParams()).setMargins(smallMargin, 0, 0, 0); 

    int marginForMessage = 0; 

    viewHolder.groupPhoto.addView(crop); 
    if (!match.seen | match.newMessages > 0) { 
     addMessages(match.newMessages, marginForMessage, viewHolder); 
    } 
} 

EDIT: Это вызвано программным добавлением изображений. После добавления изображений и их различных атрибутов внутри XML-файла вместо их добавления и объявления программных параметров все работает плавно.

+0

В то время как вы делаете что-то правильное относительно View-recycling, вы должны определенно рассмотреть возможность использования Picasso для загрузки изображения. http://square.github.io/picasso/ также изменение параметров макета во время выполнения - это не самый лучший способ - тип шкалы например centerCrop или fitCenter, может сделать вашу работу для изображения, я думаю - также вы должны иметь представления в своем XML и просто изменять видимость элементов для лучшей производительности, а не создавать или удалять их во время выполнения. –

+0

Благодарим вас за предложение - также изучая оптимизацию того, как мы обычно обрабатываем наши изображения. Однако падение производительности в нашем ListView сохраняется даже при использовании одного ImageView с небольшим оптимизированным png-файлом, загруженным из наших ресурсов. Я сомневаюсь, что использование Picasso (или аналогично доступных библиотек) решит нашу проблему с производительностью. – Thomas

+0

я бы попробовал на picasso - также поместил изображение в xml и установил его, чтобы он стал стандартным, и после того, как ваша видимая видимость исчезнет или станет видимой - это также поможет улучшить производительность. –

ответ

1

Корень проблемы, кажется, заключается в том, что вы добавляете View и устанавливаете их LayoutParams программно в Adapter. Это по своей сути «тяжелее», чем установка его в XML, и станет еще более заметным на устройствах с низким и средним уровнем.

Если у вас нет веской причины для добавления View s таким образом, вы не должны. Picasso не поможет.

Примечание: Небольшая вещь, которую я заметил, что вы не вызвали

convertView.setTag(holder); 

в методе getView(). Это упущение также может быть источником проблем с производительностью.

+0

Спасибо! Исправлено удаление программных настроек параметров. Включено все ImageViews внутри XML-файла - гладкая, плавная прокрутка. – Thomas

1

Дополнительное соображение состоит в том, что в addGroupPhoto() вы делаете по крайней мере еще один findViewById() для каждого элемента списка.

подошва цель ViewHolder шаблон кэшировать ссылки на мнения, т.е. вызывать только findViewById, когда вы настраиваете ваш ViewHolder в первый раз.

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