Это сущность созданая для замены ScreenModel. Ключевая разница в них, то что ScreenModel отражает в идеале текущее состояние объекта. В то время как BindModel служит для того чтобы организовать обмен данными между View и Presenter. Можно рассматривать BindModel как интерфейс в широком смысле этого слова.
В рамках архитектуры подразумвается организация двух направлений потоков данных
- от view к presentor`у (view > view binding > presenter)
- от presentor`a ко view (presenter > view binding > view)
- Важно отметить, что здесь не регламентируется связь презентора и модели
Под направленностью потоков подразумевается то, что данные могут быть отправлены определенным типом отправителей для определнного типа получателей. Например, view могут посылать данные только для презентора и подписаться на поток могут только презенторы и никто больше, в том числе эта возможность недоступна и для самих view.
Механизм организации направлености потоков. Подразумевает, что у потока есть отправитель и получатель. Соответственно, отправитель может быть либо источником данных для одного потока, либо получателем этих данных.
Тип источника или получателя. В данный момент сейчас это View и Presenter
Конечный объект который будет источником или получателем. Имеет тип
RelationEntity
Направленный поток данных, связывает два Related
объекта для передачи
данных.
Реализованы следующие типы:
-
Action
Деиствие исходящее от пользователя. При подписке эмитит последний объект. Симметрично State. -
State
Изменение состояния исходящее из ui/бизнес-логики. При подписке эмитит последний объект. Симетрично Action. -
Bond
Action и State в одной сущности. Deprecated. Лучше использовать совместноActon
иState
взамен -
Command
Во многом повторяет State за тем исключением, что не хранит последний объект, и потому не эмитит его при подписке.
Для инстанцирования презентера необходимо наследовать компонент экрана от BindableScreenComponent и в модуле добавить provide метод, он должен возвращать тип Any. В самом презентере нужно поставить @Inject на конструкторе. Это позволит не прописывать создание презентера вручную.
@Provides
@PerScreen
fun providePresenter(presenter: YourPresenter) = Any()
Реализация основанна на RxRely потому не принимает null. Как и вся RxJava2
Описание проблемы здесь Two-way Data Binding
По возможности, старайтесь избегать. Если все же нужно циклическое
связвание данных, то предусмотрите выход на строне презентора или вью.
Во-первых. При создании цикличных зависимостей используйте взаимно обратные
преобразования со стороны вью и презентора,
т.е. такие которые при использовании взаимно нейтрализуют друг друга.
f1(f2(x)) = y, f2(f1(y)) = x
где
x - значение передаваемое из презентера во вью (через State)
y -значение передаваемое из вью в презентер (через Action)
f1 - преобразование значения со стороны вью
f2 - преобразование значение со стороны презентора.
Во-вторых используйте оператор distinctUntilChanged()
на стороне презентора или вью
Для большей надежности имеет смысл передавать через Action/State объекты доменной модели, это уменьшит количество ошибок на перобразованиях
На вью виджет ввода суммы, который добавляет в символ валюты в конец. Виджет эмитит строку целиком: сумма+символ валюты. Со стороны презентора приходит только сумма без символа валюты - ее он и эммитит в стейт.
TwoWayActivityView
в samples
(Данный модуль является экспериментальным и не является обязательным стандартом использования в проекте) Поддежка data-binding
Основные классы:
Для подключения данного модуля из Artifactory Surf
необходимо, чтобы корневой build.gradle
файл проекта был сконфигурирован так,
как описано здесь.
Для подключения модуля через Gradle:
implementation "ru.surfstudio.android:core-mvp-binding:X.X.X"