#android #android-livedata #two-way-binding
Вопрос:
У меня возникла проблема с двусторонней привязкой к целочисленному типу данных.
Модель представления
var saleType: MutableLiveData<Int> = MutableLiveData(1)
var saleDetail: MutableLiveData<Int> = MutableLiveData(0)
var salePrice: MutableLiveData<Int> = MutableLiveData(0)
var saleRate: MutableLiveData<Int> = MutableLiveData(0)
var printAmount: MutableLiveData<Int> = MutableLiveData(1)
layout.xml
<data>
<import type="com.package.utils.DataBindingConverters" />
<variable
name="viewModel"
type="com.package.ViewModel" />
</data>
<com.google.android.material.textfield.TextInputEditText
android:id="@ id/sale_detail_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:gravity="right"
android:selectAllOnFocus="true"
android:inputType="number"
android:imeOptions="actionDone"
android:singleLine="true"
android:maxLines="1"
app:inputContent="@={DataBindingConverters.convertIntegerToString(viewModel.saleDetail)}"
/>
Преобразователи привязки данных
class DataBindingConverters {
companion object {
@InverseMethod("convertStringToInteger")
@JvmStatic
fun convertStringToInteger(value: String): Int? {
if (TextUtils.isEmpty(value) || !TextUtils.isDigitsOnly(value)) {
return null
}
return value.toIntOrNull()
}
@InverseMethod("convertIntegerToString")
@JvmStatic
fun convertIntegerToString(value: Int?): String {
return value?.toString() ?: ""
}
}
}
Происходит такая ошибка
cannot find method convertIntegerToString(java.lang.String) in class com.package.utils.DataBindingConverters
Я подумал, что было бы хорошо обработать значение для IntegerToString в двусторонней привязке, но я получаю ошибку, из-за которой не могу найти метод.
При двусторонней привязке существует ли какой-либо другой способ обработки целого числа?
Ответ №1:
Я не знаю, что app:inputContent
делает, но использования android:text
TextInputEditText
должно быть достаточно:
<com.google.android.material.textfield.TextInputEditText
...
android:text="@={ viewModel.salePriceString }"/>
Теперь вы задаетесь вопросом, что это salePriceString
такое . Это должна быть ваша 2-сторонняя привязка LiveData, и , поскольку android:text
требуется String
, salePriceString
ввод будет LiveData<String>
. Измените свою модель представления на:
val salePriceString = MutableLiveData<String?>(0.toString())
Теперь каждый раз , когда вы редактируете текст (путем ввода пользователем) в TextInputEditText
, ваш salePricesString
будет обновляться новым текстом. И в любое время, когда вы обновляете свой salePriceString
сквозной код, ваш текст TextInputEditText
будет обновляться соответствующим образом. В последнем случае, если вы хотите обновить свой salePriceString
, например, значением 500, вы бы сделали salePriceString.postValue(500.toString())
это . И если вы хотите получить Int
значение из salePriceString
своего кода, просто сделайте salePriceString.value?.toIntOrNull()
это .
Следующие шаги необязательны, но если вам нужен удобный способ получения Int
значения без использования salePriceString.value?.toIntOrNull()
каждый раз, измените свою модель представления немного дальше:
import androidx.lifecycle.Transformations
...
val salePriceString = MutableLiveData<String?>(0.toString())
// add conversion to LiveData<Int>
val salePrice = Transformations.map(salePriceString) { priceString ->
priceString?.toIntOrNull()
}
salePrice
теперь содержит Int
значение salePriceString
и автоматически обновляется при каждом salePriceString
изменении. salePrice
является a LiveData
, поэтому вы можете наблюдать его так же , как вы бы наблюдали salePriceString
, но вместо salePriceString
этого у вас есть Int
готовое значение salePrice
.
Последний шаг-понаблюдать salePrice
где-нибудь в коде, наиболее логично, за фрагментом, к которому прикреплена ваша модель представления:
viewModel.salePrice.observe(this, {}) // this, or viewLifecycleOwner, depending on your use case
Вам нужно наблюдать за этим, даже если вы потом ничего не сделаете со значением. Это потому Transformation.map
, что это немного странно, LiveData
созданное им не будет «жить», если для этого не существует наблюдателя. Это означает, что до salePrice
тех пор, пока за вами не будет наблюдать какой-либо наблюдатель, вы не получите от этого никакой ценности, т. е. salePrice.value
всегда будете null
.