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

Привязка данных к данным Android ObservableList

Мне трудно определить реальный смысл android.databinding.ObservableList как функцию привязки данных.

Сначала это выглядело как классный инструмент для отображения списков через привязка данных, добавив их через xml в RecyclerView, Для этого я сделал BindingAdapter следующим образом:

@BindingAdapter(value = {"items"}, requireAll = false)
public static void setMyAdapterItems(RecyclerView view, ObservableList <T> items) {
    if(items != null && (view.getAdapter() instanceof MyAdapter)) {
        ((GenericAdapter<T>) view.getAdapter()).setItems(items);
    }
}

Таким образом, я могу использовать атрибут app:items в RecyclerView с MyAdapter, установленным для него, для обновления его элементов.

Теперь лучшая функция ObservableList заключается в том, что вы можете добавить к ней OnListChangedCallback, который обрабатывает те же события, которые доступны в RecyclerView, чтобы добавлять/перемещать/удалять/изменять элементы в нем, не перезагружая весь список.

Итак, логика, которую я решил реализовать, - это параграф:

  • Я начинаю с пустой MyAdapter
  • Когда мои объекты извлекаются из моих API-интерфейсов, я создаю экземпляр ObservableArrayList и переношу его в binding
  • Связывание данных вызывает мой BindingAdapter перенос элементов на MyAdapter
  • Когда MyAdapter получает новые элементы, он очищает свои старые и добавляет OnListChangedCallback к ObservableList, полученному для обработки микро-изменений
  • Если что-то изменится в ObservableList, MyAdapter изменится соответственно без обновления полностью
  • Если я хочу отобразить совершенно другой набор одинаковых типов элементов, я могу просто повторно установить переменную binding, поэтому снова будет вызываться BindingAdapter, и элементы MyAdapter будут полностью изменены.

Например, если я хочу отображать элементы типа Game, у которых у меня есть два разных списка: "Собственные игры" и "Игры в список желаний", я мог бы просто вызвать binding.setItems(whateverItems), чтобы полностью обновить отображаемые элементы, но например, если я перемещаю "списки желаний" вокруг списка, чтобы организовать их по релевантности, в каждом списке будут выполняться только микро-изменения без обновления всего.

Оказывается, эта идея была неосуществима, потому что привязка данных повторно выполняет BindingAdapter каждый раз, когда одно изменение выполняется в ObservableList, так что, например, я наблюдаю за поведением:

  • Я начинаю с пустой MyAdapter
  • Когда мои объекты извлекаются из моих API-интерфейсов, я создаю экземпляр ObservableArrayList и переношу его в binding
  • Связывание данных вызывает мой BindingAdapter перенос элементов на MyAdapter
  • Когда MyAdapter получает новые элементы, он очищает свои старые и добавляет OnListChangedCallback к ObservableList, полученному для обработки микро-изменений
  • Если что-то изменяется в ObservableList, снова вызывает BindingAdapter, таким образом MyAdapter снова получает весь список и полностью обновляется.

Это поведение кажется мне совершенно неподходящим, поскольку предотвращает использование ObservableList в привязке данных xml. Я не могу всерьез выяснить законный случай, когда это поведение желательно.

Я посмотрел несколько примеров: здесь и этот другой вопрос SO

В первой ссылке все примеры использовали ObservableList непосредственно в Adapter, даже не пропустив форму xml и фактическую привязку данных, а в коде, связанном с ответом SO, разработчик сделал в основном то же самое Я попытался сделать, добавив:

if (this.items == items){
        return;
}

в начале своего Adapter.setItems(ObservableList<T> items), чтобы отбросить все случаи, когда метод вызывается из-за простых изменений в ObservableList.

Какая потребность в этом поведении? Какие могут быть случаи, когда такое поведение желательно? Я чувствую, что ObservableList - это функция, добавленная с привязкой данных, и действительно полезна, за исключением случаев, когда используется с фактической привязкой данных, и в этом случае она заставляет вас защищаться от ее поведения. Если я объявляю его как простой List в тегах данных xml и в подписи BindingAdapter, тогда я могу вернуть его обратно в ObservableList внутри MyAdapter, и он работает нормально, но это довольно плохо хак. Если бы это была просто отдельная функция от привязки данных, не вызывая привязки при каждом изменении, это было бы намного лучше, на мой взгляд.

4b9b3361

Ответ 1

В соответствии с примером, представленным в документах https://developer.android.com/topic/libraries/data-binding/index.html#observable_collections, ObservableList используется для доступа к ним с использованием целых чисел, например:

<data>
    <import type="android.databinding.ObservableList"/>
    <import type="com.example.my.app.Fields"/>
    <variable name="user" type="ObservableList&lt;Object&gt;"/>
</data>
…
<TextView
   android:text='@{user[Fields.LAST_NAME]}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

Поэтому, когда что-то изменяется внутри ObservableList, он вызывает BindingAdapter для обновления интерфейса. Я думаю, что это основная цель использования ObservableList, пока DataBinding находится в состоянии разработки. Возможно, в будущем DataBinding будет обновлен новым SomeObservableList, который будет использоваться в RecyclerView. Между тем, вы можете использовать if (this.items == items){return;}, если он работает для вас, или пересмотреть свою логику использования ObservableList.