2016-08-18 1 views
1

Я создал собственный класс BaseAdapter для отображения регистрационных ключей в ListView. Всякий раз, когда я добавляю еще один ключ в список и вызываю notifyDataSetChanged(), обновления ListView визуально просто прекрасны. Моя структура данных - это просто ArrayList простых структур, содержащих несколько строк и int. Однако, когда я пытаюсь очистить список ключей и позвонить notifyDataSetChanged(), ничего не происходит визуально. Когда я закрываю и снова открываю приложение, список пуст, как и должно быть. Перед вызовом notifyDataSetChanged() Теперь я звоню notifyDataSetInvalidated(). Это позволяет корректно обновлять изображения, как только я удаляю ключи, но Google documentation предупреждает об использовании этого метода, если вы не полностью используете этот адаптер. Когда я регистрирую больше ключей после их очистки, они все еще отображаются в ListView, что делает его похожим на то, что notifyDataSetInvalidated() является рабочим решением. Есть ли какая-либо опасность, связанная с этим методом, если я буду использовать один и тот же BaseAdapter и ArrayList для ListView? Есть ли лучшее решение? Вот мой заказ реализация BaseAdapter:BaseAdapter неправильно удаляет элементы из представления?

class KeyAdapter extends BaseAdapter implements Database.KeyRegistrationListener { 

    private ArrayList<Database.KeyDetails> keyInfo; 

    public KeyAdapter(ArrayList<Database.KeyDetails> keyInfo) { 

     this.keyInfo = keyInfo; 

    } 

    @Override 
    public int getCount() { 

     return keyInfo.size(); 

    } 

    @Override 
    public Database.KeyDetails getItem(int position) { 

     return keyInfo.get(position); 

    } 

    @Override 
    public long getItemId(int position) { 

     return position; 

    } 

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

     TextView userID; 
     TextView appName; 
     TextView date; 
     TextView time; 

     if (convertView == null) { 

      convertView = getLayoutInflater().inflate(R.layout.registration_item, parent, false); 

      userID = (TextView) convertView.findViewById(R.id.user_id); 
      appName = (TextView) convertView.findViewById(R.id.app_name); 
      date = (TextView) convertView.findViewById(R.id.date_used); 
      time = (TextView) convertView.findViewById(R.id.time_used); 

      convertView.setTag(R.id.user_id, userID); 
      convertView.setTag(R.id.app_name, appName); 
      convertView.setTag(R.id.date_used, date); 
      convertView.setTag(R.id.time_used, time); 

     } else { 

      userID = (TextView) convertView.getTag(R.id.user_id); 
      appName = (TextView) convertView.getTag(R.id.app_name); 
      date = (TextView) convertView.getTag(R.id.date_used); 
      time = (TextView) convertView.getTag(R.id.time_used); 

     } 

     Database.KeyDetails key = getItem(pos); 

     userID.setText(key.userID); 
     appName.setText(key.appName); 
     date.setText(key.date); 
     time.setText(key.time); 

     return convertView; 

    } 

    @Override 
    public void notifyKeysUpdated(Database.KeyDetails newKeyDesc) { 

     if (newKeyDesc == null) { 

      keyInfo.clear(); 
      notifyDataSetInvalidated(); 
      notifyDataSetChanged(); 

     } else{ 

      keyInfo.add(newKeyDesc); 
      notifyDataSetChanged(); 

     } 

    } 

} 

Метод notifyKeysUpdated() называется мой класс-оболочку для базы данных SQLite всякий раз, когда я добавить ключ в базу данных. Если мой объект базы данных подает прослушиватель null, это означает, что все ключи в базе данных были очищены, а ListView должен быть визуально пустым.

EDIT: Так как я начал использовать notifyDataSetInvalidated(), то ListView больше не отображает ничего, в том числе, когда я зарегистрировать новые ключи.

ответ

0

В конце концов, проблема просто оказалась ошибкой со ссылкой на мои данные. Поскольку Java является очень безопасным языком и не допускает явных указателей, я предполагаю, что в какой-то момент вдоль строки я сделал копию объекта данных, вместо того, чтобы передавать тот, который я собирался обновить в ListView. После упрощения моего кода и создания и передачи данных в таблицу самым простым способом, он полностью работоспособен.

1

После выполнения некоторых исследований на исходном коде BaseAdapter и ListView в Android, а также этот вопрос (Android - What does adapter.notifyDataSetInvalidated do?)

Первое, что вы можете быть уверены, что это, Ваши данные не полностью привязки к адаптеру. Обычно BaseAdapter представляет собой всего лишь набор интерфейсов, и он не содержит никакого поля массива. Это означает, что размер, выбор данных на вас. Чтобы указать, что набор данных больше недействителен, вы должны переопределить метод notifyDataSetInvalidated().

Я попытался скопировать код в свой проект. Оба метода notifyDataSetInvalidated() и notifyDataSetChanged() будут обновлять весь список, который утвердил, что arraylist не полностью привязан к адаптеру. Это всего лишь адаптер для получения списка данных. Мне интересно, что в документации Google не ясно объясняется, что делать с этим методом.

+0

Во всех других реализациях BaseAdapter, которые я видел, пользовательский подкласс просто сохранил собственную структуру данных и реализовал несколько методов, которые я сделал. Список определенно обновляется, это просто потому, что по какой-то причине представление обновляется только после добавления в список, но не при удалении элементов. Я думаю, что я могу вместо этого перейти на CursorAdapter, учитывая, что ключи, зарегистрированные в моем приложении, изначально хранятся в базе данных SQLite. Спасибо за усилия, хотя! –

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