Представление привязки данных Android, созданное программно

Документация Android отлично описывает, как можно создать класс привязки с помощью XML-файла макета. Но у меня есть пара вопросов.

Есть ли способ создать класс привязки данных для пользовательского представления, которое создается программно? Например, предположим, что у меня есть два настраиваемых класса представления, и я хочу программно связать с ними один и тот же объект модели представления без использования XML. Классы следующие:

class MyViewModel {
}

class MyCustomView extends View {
}

class MyAnotherCustomView extends MyCustomView {
}

Теперь скажем, я создаю экземпляр MyCustomView/MyAnotherCustomView, используя:

MyCustomView customView = new MyCustomView(context);

Как в этом случае использовать привязку данных? Возможно ли это с помощью официальной структуры привязки данных Android? Если нет, то какие другие фреймворки/библиотеки доступны или рекомендуются для достижения этой цели?

Мой второй вопрос является продолжением первого вопроса. Допустим, невозможно достичь того, чего я хочу в своем первом вопросе. Затем мне нужно будет определить файл my_custom_view.xml. Это будет выглядеть примерно так:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <com.example.name.MyCustomView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:text="@{user.firstName}"/>
</layout>

Теперь, если я хочу использовать MyAnotherCustomView, который является подклассом MyCustomView, сохраняя логику привязки такой же, мне придется создать новый файл xml my_another_custom_view.xml только для замены MyCustomView на MyAnotherCustomView для определения той же привязки?


person androholic    schedule 01.12.2016    source источник
comment
см. DataBindingUtil#bind(View root)   -  person pskink    schedule 01.12.2016
comment
Я уже проверил это, но, похоже, это не помогает моему варианту использования. Можете ли вы опубликовать рабочий пример? Может быть, это поможет прояснить ситуацию. Спасибо!   -  person androholic    schedule 01.12.2016
comment
"and I want to bind the same view model object to them programmatically without using any xml о, извините, я пропустил это, так чего именно вы пытаетесь достичь? привязки определены только в xml, так как же вы хотите определить сопоставление между данными и представлениями?   -  person pskink    schedule 01.12.2016
comment
Ага. Вот моя ситуация. У меня есть настраиваемая иерархия наследования групп просмотра. Каждая из этих пользовательских групп просмотра программно создает свою иерархию представлений. Они не раздувают макет с помощью xml. Все эти классы должны прослушивать модели представления, которые передают им данные. Поэтому я хотел знать, можно ли определить привязку программно.   -  person androholic    schedule 01.12.2016
comment
поэтому в этом случае вы должны использовать Observable, подробнее здесь: developer.android.com/topic/libraries/data-binding/   -  person pskink    schedule 01.12.2016
comment
Да я в курсе. Но мне просто было интересно, смогу ли я каким-то образом вписаться в структуру привязки данных Android по умолчанию в моем дизайне. А если я использую observable, то мне придется вручную регистрироваться и отписываться от событий обратного вызова, если я не ошибаюсь, чего я хотел избежать. Спасибо за вашу помощь :)   -  person androholic    schedule 01.12.2016
comment
так что либо зарегистрируйтесь, либо отмените регистрацию из обратного вызова или привязки xml, имхо нет третьего способа, но я все же не понимаю, почему вы не хотите использовать xml, даже если ваш пользовательский интерфейс является своего рода динамическим, он может быть составлен из нескольких макетов привязки данных xml   -  person pskink    schedule 01.12.2016
comment
Ага. Я могу. Но пользовательские группы представлений имеют довольно сложную иерархию представлений, и я не хотел создавать xml для каждого подкомпонента в группе просмотра. Но привязка данных Android кажется разовой инвестицией. Так что обязательно посмотрю. Спасибо!   -  person androholic    schedule 01.12.2016


Ответы (1)


Ответ на первый вопрос: «Нет». Для привязки данных Android требуется XML для создания классов привязки.

Во втором вопросе вы предлагаете решение, которое будет работать. Если вы пойдете по этому пути, один из способов сделать это — использовать установщики базового класса ViewDataBinding для установки ваших переменных. Я могу представить себе такой метод:

public void addCustomView(LayoutInflater inflater, ViewGroup container, User user) {
    ViewDataBinding binding = DataBindingUtil.inflate(inflater,
        this.layoutId, container, true);
    binding.setVariable(BR.user, user);
}

Здесь я предположил, что выбор пользовательского представления определяется полем layoutId. Каждый возможный макет должен будет определить переменную user типа User.

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

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
   <data>
       <import type="android.view.View"/>
       <variable name="user" type="com.example.User"/>
       <variable name="viewChoice" type="int"/>
   </data>
   <FrameLayout ...>
       <!-- All of your outer layout, which may include binding
            to the user variable -->
       <ViewStub android:layout="@layout/myCustomView1"
                 app:user="@{user}"
                 android:visiblity="@{viewChoice == 1} ? View.VISIBLE : View.GONE"/>
       <ViewStub android:layout="@layout/myCustomView2"
                 app:user="@{user}"
                 android:visiblity="@{viewChoice == 2} ? View.VISIBLE : View.GONE"/>
    </FrameLayout>
</layout>
person George Mount    schedule 02.12.2016
comment
Потрясающий! Спасибо, Джордж. Я думаю, что решение, которое вы упомянули, достаточно хорошо, чтобы удовлетворить мои требования. - person androholic; 02.12.2016
comment
Очень ценю и благодарю Джорджа, вы помогаете нам, и это здорово !!! - person mochadwi; 28.02.2020