Двусторонняя привязка Android с целочисленным типом(Livedata)

#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 .