Подтвердить что ты не робот

Android. Как работает метод notifyDataSetChanged() и ListViews?

Я пытаюсь понять концепцию ListView и как она работает, и я пытаюсь создать свой собственный адаптер, который расширяет BaseAdapter. Например, для ArrayAdapter существует метод notifyDataSetChanged(), который следует вызывать после обновления списка массивов, который содержит все ваши данные, чтобы обновить ListView.

Но я создаю свой собственный подкласс BaseAdapter. Этот метод недоступен мне или не так ли? Как реализовать этот метод? В принципе, что делает этот метод, возможно, я тогда пойму.

В случае ArrayAdapter я предполагаю, что он смотрит, в какой позиции отображается ListView, и проверяет, совпадает ли он с тем же именем, что и в ArrayList после его обновления? Или...

В нем говорится, что метод:

Сообщает заинтересованным наблюдателям, что базовые данные были изменен, и любой вид, отражающий набор данных, должен обновиться.

Но как именно он обновляется?

Может кто-нибудь объяснить пожалуйста?

4b9b3361

Ответ 1

Я понял это. Я не мог понять, как, черт возьми, начался адаптер и как он узнал, откуда взять данные. Когда я расширил класс BaseAdapter, в конструкторе этого класса я инициализировал список элементов, которые я хотел видеть в ListView. Но я не мог понять, как эти значения будут использоваться и когда.

Так вот вещь !!! :

В BaseAdapter есть несколько методов, которые необходимо переопределить. Среди них есть getCount().

Когда ListView создан и еще много чего, он вызывает getCount(). Если это возвращает значение, отличное от 0 (я возвратил размер ArrayList, который я ранее инициализировал в конструкторе), то он вызывает getView() достаточное количество раз, чтобы заполнить экран элементами. Например, я инициализировал ArrayList с 20 элементами. Поскольку на экране изначально помещалось только 8 элементов, getView() вызывался 8 раз, каждый раз запрашивая позицию, которую я должен был вернуть (точнее, он хотел знать, как будет выглядеть строка в списке в этой конкретной позиции). какие данные нужно было содержать). Если я прокручиваю список вниз, getView() снова и снова, пока я не достигну конца списка, в моем случае 20 элементов/строк.

Что notifyDataSetChanged() делает... при вызове он смотрит, какие элементы отображаются на экране в момент его вызова (точнее, какие индексы строк), и вызывает getView() с этими позициями.

т.е. если вы отображаете первые 8 элементов в списке (то есть те, которые видны на экране), и вы добавляете другой элемент между 2-м и 3-м элементом в списке и вызываете notifyDataSetChanged() тогда getView() 8 раз, с позициями, начинающимися с 0 и заканчивающимися на 7, и поскольку в getView() вы получаете данные из ArrayList он автоматически вернет новый элемент, вставленный в список, вместе с 7 из предыдущих 8 (7). а не 8, потому что последний элемент переместился на одну позицию вниз, так что он больше не виден), и ListView будет перерисовывать, или что-то еще, с этими элементами.

Кроме того, важно указать, что если вы правильно реализовали getView(), вы в конечном итоге переработаете уже отображенные элементы (объекты) (вместо создания новых). Посмотрите это видео примерно в 12:00 минут, чтобы увидеть правильный способ реализации getView()

Я понял все это путем размещения вызовов LogCat в каждом методе и отслеживания происходящего.

Надеюсь, это поможет тому, кто только сейчас начинает понимать, как работает ListView.

PS Этот пример также очень помог мне понять.

ОБНОВИТЬ

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

Здесь ссылка для справки: https://developer.android.com/guide/topics/ui/layout/recyclerview

Ответ 2

BaseAdapter может быть "наблюдаться" другими классами. Когда вы вызываете метод ListView setAdapter(), он вызывает registerDataSetObserver адаптера. Итак, адаптер знает, кто интересуется новыми данными.

Здесь вы можете проверить источник BaseAdapter . Это довольно мало.

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

Ответ 3

Предположим, что ваш ListView отображает некоторые данные, хранящиеся в ArrayList.

После изменения содержимого ArrayList вам необходимо сообщить списку, что источник данных был изменен, и ему нужно перерисовать его, чтобы показать новые данные.

Итак, вот где notifyDatasetChanged(). Он сообщает ListView, что данные были изменены; и чтобы показать новые данные, ListView необходимо перерисовать.

Ответ 4

Поскольку вы расширяете BaseAdapter для своего собственного создания подкласса, вы также получите метод notifyDataSetChanged().