#android #listview #layout
#Android #listview #макет
Вопрос:
Приложение завершает работу после нескольких секунд прокрутки в listview.
String[] names = new String[] {"Cook","2/Person/15/5","Cashier","2/Person/15/5"};
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View rowView = convertView;
LayoutInflater inflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
String[] info = names.get(position).split("/");
if (rowView == null) {
if (info.length != 1) {
rowView = inflater.inflate(R.layout.employee, null, true);
holder = new ViewHolder();
holder.name = (TextView) rowView.findViewById(R.id.name);
holder.money= (TextView) rowView.findViewById(R.id.money);
holder.rating = (RatingBar) rowView.findViewById(R.id.rating);
rowView.setTag(holder);
}else{
rowView = inflater.inflate(R.layout.lable, null, true);
holder = new ViewHolder();
holder.lable = (TextView) rowView.findViewById(R.id.name);
rowView.setTag(holder);
}
}
holder = (ViewHolder) rowView.getTag();
if (holder.lable==null) {
holder.name.setText(info[1]);
holder.money.setText(info[2]);
holder.rating.setRating(Float.valueOf("1"));
}else{
holder.lable.setText(names.get(position));
}
//}
return rowView;
}
Комментарии:
1. Используйте Logcat, чтобы увидеть точное сообщение об ошибке:
adb logcat
или перспективу DDMS в eclipse2. в нем говорилось, что nullPointerexeption @ holder.lable.setText(names.get (позиция));
Ответ №1:
Поскольку вы используете представления Viewholder-pattern и recycle, в итоге получается jumble. Это потому, что у вас в списке есть два разных вида представлений, и когда вы получаете convertview, это будет одно из этих представлений.
Представьте набор данных A с макетом / представлением a, и то же самое для B b
(-B- означает, что он еще не отображается на экране) Итак, если ваш первоначальный список Aa, Bb, Bb, Aa, -B-, -B- и вы прокручиваете, чтобы внести данные B в список.. Тогда вы получите convertview с макетом a или макетом b, таким образом, не имея возможности надежно использовать convertview.
Я провожу некоторый поиск, чтобы найти способ поддерживать разные представления в ListView и в то же время использовать шаблон convertView / ViewHolder.. Пока что я нахожу этот вариант интересным:https://github.com/commonsguy/cwac-merge#readme
Что вы хотите сделать, так это переопределить getItemViewType (позицию) . Вот пример. У вас, конечно, есть свои типы данных вместо MoreResultsLoader и YPContact .
@Override
public int getItemViewType(int position) {
if (resultsList.get(position) instanceof MoreResultsLoader) {
return VIEW_TYPE_MORE_RESULTS_LOADER;
}
if (resultsList.get(position) instanceof YPContact) {
YPContact ypCon = (YPContact) resultsList.get(position);
if(checkForGold(ypCon))
return VIEW_TYPE_YPCONTACT_GOLD;
else
return VIEW_TYPE_YPCONTACT_REG;
}
}
Затем в getView вам нужно было бы проверить, с каким типом представления вы имеете дело, и раздуть / заполнить правильный класс ViewHolder.
public View getView(final int position, View convertView, ViewGroup parent) {
View ourView = convertView;
int itemViewType = getItemViewType(position);
switch (itemViewType) {
case VIEW_TYPE_MORE_RESULTS_LOADER:
MoreResultsViewHolder moreResVH = null;
if (ourView == null) {
ourView = layoutInflator.inflate(R.layout.load_more_items,
null, true);
moreResVH = new MoreResultsViewHolder(ourView);
ourView.setTag(moreResVH);
} else {
moreResVH = (MoreResultsViewHolder) ourView.getTag();
}
if (moreResVH != null) {
moreResVH.populate((MoreResultsLoader) resultsList
.get(position), context);
}
return ourView;
case VIEW_TYPE_YPCONTACT_GOLD:
ContactViewHolderGold contactVHGold = null;
if (ourView == null) {
ourView = layoutInflator.inflate(
R.layout.yp_search_result_list_item_gold, null, true);
contactVHGold = new ContactViewHolderGold(ourView);
ourView.setTag(contactVHGold);
} else {
contactVHGold = (ContactViewHolderGold) ourView.getTag();
}
if (contactVHGold != null) {
final YPContact ypContact = (YPContact) resultsList
.get(position);
contactVHGold.populate(ypContact, mCurrentLocation,
ypSearchResultsActivity);
// moreResVH.populate(
// (MoreResultsLoader)resultsList.get(position),context);
}
return ourView;
Ответ №2:
В Android есть инструмент отладки logcat в перспективе ddms, где вы найдете журналы. Вы могли бы точно определить номер строки, в которой происходит сбой кода.
convertView в основном используется, когда все элементы списка одинаковы. Поскольку это помогает в переработке представлений. Здесь мы не уверены, является ли переработанный вид R.layout.employee или R.layout.ярлык. Это может быть причиной проблемы.
Опять же, это предположение. Logcat поможет вам сузить проблему.
Ответ №3:
Посмотрите на первый элемент "Cook"
:
String[] names = new String[] {"Cook","2/Person/15/5","Cashier","2/Person/15/5"};
Вы делаете:
String[] info = names.get(position).split("/");
И затем:
holder.name.setText(info[1]);
holder.money.setText(info[2]);
Мне не нужно заглядывать в logcat, чтобы увидеть ArrayIndexOutOfBoundsException
Комментарии:
1. О, извините, я добавил в первую строку, чтобы помочь людям понять код. Это должен быть arrayadapter, который содержит строки.
2. Хорошо, но вы не проверяете данные, я имею в виду
info[1]
иinfo[2]
.3.
split
может возвращать массив длиной 0,1,2,… Проверьте длину массива перед доступом к элементам.4. Но logcat уточнит, какая у вас проблема.
5. проблема с сбоем устранена, но теперь список становится беспорядочным. При прокрутке макета ярлыка иногда отображается неправильная строка. Подобная табличка отображала бы «2 / Person / 15 / 5» вместо «Cook».