Почему происходит ошибка?
Когда вы определяете двустороннюю привязку данных, как это android:text="@={Converter.doubleToString(d)}"
, возникает вопрос: где данные должны быть переданы из EditText
? Должен ли он быть передан в Converter.doubleToString
или, может быть, другую stati c функцию из Converter
, возможно, в результат Converter.doubleToString(d)
или в d
переменную?
Вы должны быть точными.
Вы ожидаете, что это d
, компилятор ожидает, что это результат Converter.doubleToString(d)
. На самом деле, ни то, ни другое не будет работать.
Теперь EditText
работает с символами. Он ничего не знает о double, int, float, byte, short, boolean или о чем-либо еще, кроме строки.
Это означает, что для реализации двусторонней привязки данных ваш источник:
- обязательно возвращаемое значение типа String;
- должно быть присваиваемым.
Как решить проблему?
Android компоненты архитектуры знакомят нас с классом ObservableField
. Есть готовые к использованию ObservableBoolean
, ObservableChar
, ObservableFloat
и еще несколько. Если вы откроете ссылку из предыдущего предложения, вы увидите все классы Observable...
на левой панели.
Нет ObservableString
, но ObservableField
принимает общий c тип. Таким образом, вы можете определить переменную, которая является частью привязки данных, как ObservableField<String>("defaultValueHere")
.
Итак, у вас должно быть:
class StockLoadTaskModel : ViewModel() {
....
....
var d: Double = 10.0
var dataBindingVariable = ObservableField<String>(d.toString())
}
dataBindingVariable
всегда будет возвращать вам содержимое EditText
, к которому вы его привязали. Вы можете получить это значение и безопасно преобразовать его в double.
class StockLoadTaskModel : ViewModel() {
....
....
var d: Double = 10.0
var dataBindingVariable =
object: ObservableField<String>(d.toString()) {
override fun set(value: String?) {
super.set(value)
// a value has been set
d = value.toDoubleOrNull() ?: d
}
}
}
Объявление макета будет выглядеть так, как для поля ввода:
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_quantity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:text="@={viewModel.dataBindingVariable}"
android:hint="@string/quantity" />
</com.google.android.material.textfield.TextInputLayout>
И не будет необходимости в object Converter
.
Существует еще один способ двусторонней привязки данных, о котором я не говорю здесь, потому что на него уже был дан ответ. Вот .