Setter and getter methods of the model have one parameter, like this:
public int getPrice(Object key) {
}
public void setPrice(Object key, int price) {
}
XML looks like this:
<EditText
android:id="@+id/edtPrice"
style="@style/CreateShipperItemValueEditTextView"
android:layout_centerVertical="true"
android:hint="@string/hint_price"
android:inputType="number"
android:maxLines="1"
android:text="@={shipper.getPrice(priceKey)}"/>
android:text="@={shipper.getPrice(priceKey)}"
Compiler errors during the building say that we should you use @InverseMethod annotation. I try something like this:
@InverseMethod(value = "getPrice")
@Override
public void setPrice(Object key, int price) {
super.setPrice(key, price);
}
But in this case I have the next error.
error: @InverseMethods must have a non-void return type
So I will be glad to here nice explanation of the whole flow. Thanks
Nice to see you're using the new InverseMethod available in Android Studio 3.0.
You're using two-way data binding with a method and the expression must understand how to set the value when the user modifies the text. The use is intended for conversion methods, so I don't know if this applies in your case.
Essentially, data binding uses code like this when setting the text to the View:
EditText edit = binding.edtPrice;
edit.setText(shipper.getPrice(priceKey));
And when the text changes, you are asking it to do this:
EditText edit = binding.edtPrice;
priceKey = shipper.setPrice(priceKey, edit.getText());
That's clearly not going to work and it gives you an error.
There are two things wrong, really. The first is that getPrice()
returns an int
instead of a CharSequence
or String
. The second is that setPrice()
isn't really doing a conversion -- it takes a different number of parameters and returns a void
.
In your case, you're not trying to convert priceKey into an integer; you're trying to access a value in a map of some sort. There are a few ways to handle this. I think the easiest way is to use a map directly in your model. Here, I'll assume that you have a final field, but you could return it as a property using getters and setters:
public class ShipperModel {
public final ObservableArrayMap<Object, Integer> price = new ObservableArrayMap<>();
//...
}
and then in your expression:
<EditText android:text="@={`` + shipper.price[priceKey]}" .../>
If you want custom conversions, you can do it like this:
@InverseMethod("convertToPrice")
public String convertFromPrice(Object key, int price) {
//...
}
public int convertToPrice(Object key, String text) {
//...
}
And then you would pass the price object in the expression:
<EditText android:text="@={shipper.convertFromPrice(priceKey, shipper.price)}" .../>
I would simplify the conversion methods to make them reusable throughout my application and just convert an integer to String and back:
public class Converters {
@InverseMethod("fromPrice")
public static final int toPrice(String text) {
//...
}
public static final String fromPrice(int price) {
//...
}
}
and then the expression would be:
<EditText android:text="@={Converters.fromPrice(shipper.price[priceKey])}" .../>