2015-04-30 2 views
0

В настоящее время я пишу пользовательский BaseAdapter для ListView на Android. Список адаптер в основном работает хорошо, когда я первый вставки элементов в ListView, но при вставке новых элементов в середине, неправильные элементы отображаются после вызоваListView с расширенным базовым адаптером не обновляется должным образом

notifyDataSetChanged(); 

Вот упрощенный пример (ив раздели его вниз только необходимому, если я пропустил положить в какой-либо информации, пожалуйста, укажите комментарий):

public class FriendListAdapter extends BaseAdapter { 

    private ArrayList<SingleFriend> data; 
    private Activity activity = null; 

    private static int needAccept = -1; 
    private static int friend = -2; 
    private static int waiting = -3; 

    public FriendListAdapter(Activity a) { 
     this.activity = a; 
     data = new ArrayList<>(); 
    } 

    public void AddFriend(SingleFriend newFriend, boolean silent) { 

     int insertInto = 0; 

     switch (newFriend.getFriendType()) { 
      case TYPE_FRIEND_WAIT_FOR_YOUR_ACCEPT: 
       insertInto = needAccept; 
       break; 
      case TYPE_FRIEND_WAIT_FOR_HIS_ACCEPT: 
       insertInto = waiting; 
       break; 

      case TYPE_FRIEND_ACCEPTED: 
       insertInto = friend; 
       break; 
     } 

     if (insertInto < 0) { 
      boolean found = false; 
      boolean inserted = false; 
      int index = 0; 

      do { 
       if (data.get(index).getFriendID() == insertInto) { 
        found = true; 
       } else if (found) { 
        if (data.get(index).getFriendID() < 0) { 
         data.add(index, newFriend); 
         inserted = true; 
        } else { 
         if (newFriend.getFriendName().compareToIgnoreCase(data.get(index).getFriendName()) < 0) { 
          data.add(index, newFriend); 
          inserted = true; 
         } 
        } 
       } 
       if (!inserted && index == data.size() - 1) { 
        data.add(newFriend); 
        inserted = true; 
       } 
       ++index; 
      } while (index < data.size() && !inserted); 
     } 
     if (!silent) { 
      notifyDataSetChanged(); 
     } 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     View vi = convertView; 
     if (vi == null) { 
      LayoutInflater inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      SingleFriend friend = (SingleFriend)getItem(position); 
      if (friend != null) { 
       switch (friend.getFriendType()) { 
        case TYPE_SEPARATOR: 
         vi = inflater.inflate(R.layout.friendlist_topic, null); 
         vi.setTag(friend); 
         ((TextView)vi.findViewById(R.id.friendTopic)).setText(friend.getFriendName()); 
         break; 
        case TYPE_FRIEND_ACCEPTED: 
        case TYPE_FRIEND_WAIT_FOR_HIS_ACCEPT: 
        case TYPE_FRIEND_WAIT_FOR_YOUR_ACCEPT: 
         // TODO: Community rating! 
         vi = inflater.inflate(R.layout.friendlist_item, null); 
         vi.setTag(friend); 
         ((TextView)vi.findViewById(R.id.friendName)).setText(friend.getFriendName()); 
         break; 
        default: 
         break; 
       } 
      } 
     } 
     return vi; 
    } 
} 

Почему отображаются неверные данные, после того, как список друзей вставляется в список друзей? Я что-то упускаю? Даже invalidate() не показывает правильные вещи (я знаю, invalidate - это плохая опция, а я только что сделал это для тестирования). Заранее спасибо!

ответ

1

Есть слишком много проблем, но я думаю, что один вы адресация вызван (или в основном вызвано) эта проверка состояния:

if (vi == null) {... 

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

Другие проблемы, которые я заметил это,

notifyDataSetChanged предполагается назвать каждый список адаптер соединен с модифицируется. Если вы хотите скрыть некоторые элементы, вы должны сохранить два списка. Адаптер предназначен только для дисплея.

Я думаю, что вы хотите вставить элементы в список в зависимости от наличия идентификатора. Если это так, то гораздо лучший способ, чем перекодирование списка, ищущего идентификатор, - использовать карту, такую ​​как HashMap<id, SingleFriend>, к которой можно получить случайным образом get(id).

Вы должны сначала понять, как getView работает и правильно использует View Holder pattern.

+0

Спасибо, я попробую это. И нет, никогда не будет скрытых данных, то, что будет вставлено, будет показано в списке. Но спасибо за эту информацию! Редактировать: Большое спасибо, проблема, на которую вы указали, была причиной моей ошибки. Чтобы избежать повторного раздувания просмотров после того, как что-то было вставлено, следует сохранить представление для каждого элемента, чтобы вернуть его в getView, и только надуть, если эта ссылка равна нулю или это будет плохо? – Nidhoegger

+0

Да, но я вижу 'if (! Silent)' который вызывает 'notifyDataSetChanged'. Эта проверка не требуется, и notifyDataSetChanged следует вызывать каждый раз. В любом случае, я надеюсь, что это сработает для вас. – inmyth

+0

Беззвучный вариант - это еще одна функция, которая вставляет в список друзей. Он вызывает себя notifyDataSetChanged после вставки более одного друга. Я хотел, чтобы список не обновлялся часто, когда это не было необходимо. – Nidhoegger

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