所以,我有一个非常简单的问题,我似乎无法在数据绑定中格式化来自ObservableField的double。我有以下布局:
android:text='@{String.format("%.2f€", transaction.value)}'
这里是transaction.value的定义:
public final ObservableField<Double> value = new ObservableField<>();
我总是收到这个错误:
java.util.IllegalFormatConversionException:f!= android.databinding.ObservableField
如果我使用ObservableDouble,我会遇到同样的问题。避免这种情况的唯一方法似乎是我在绑定中调用transaction.value.get()
,但我认为这里可以省略get / set,因为我成功地做了例如使用ObservableField<Date>
。
我使用buildTools 26.0.2定位Sdk 26。
更新1
我现在尝试使用之前的设置做同样的事情,就像我记得的那样,它起作用了。所以我确定Gradle版本从2.3.1更改为3.0.1(即使我将目标/编译Sdk 26和buildToolsVersion 26.0.2与Gradle 2.3.1一起使用)。
正如@dominicoder指出要查看生成的数据绑定,这里有区别,解释了问题:
Gradle 2.3.1:
android.databinding.ObservableField<java.lang.Double>transactionValue=null;
java.lang.Double transactionValueGet=null;
....
if(transaction!=null){
// read transaction.value
transactionValue=transaction.value;
}
updateRegistration(3,transactionValue);
if(transactionValue!=null){
// read transaction.value.get()
transactionValueGet=transactionValue.get();
}
// read String.format("%.2f€", transaction.value.get())
stringFormatJavaLangString2fTransactionValue=java.lang.String.format("%.2f€",transactionValueGet);
Gradle 3.0.1:
android.databinding.ObservableField<java.lang.Double> transactionValue = null;
// NO transactionValueGet field !!!
....
if(transaction!=null){
// read transaction.value
transactionValue=transaction.value;
}
updateRegistration(3,transactionValue);
// read String.format("%.2f€", transaction.value)
stringFormatJavaLangString2fTransactionValue=java.lang.String.format("%.2f€",transactionValue);
所以 - 看起来这是该版本更新中引入的一个错误(为了安全起见,我创建了一个具有类似设置的全新项目,TextView使用{{1}将文本绑定到ObservableField<Double>
}})。或许它可能是预期的行为,但我真的不明白这种改变的目的。
更新2
目前问题存档于Android issue tracker
答案 0 :(得分:0)
检查数据绑定生成的java文件以获取布局。你会发现这样的东西:
android.databinding.ObservableField<java.lang.Double> transactionValue = null;
// read String.format("%.2f€", accountViewModel.test)
stringFormatJavaLangString2fAccountViewModelTest = java.lang.String.format("%.2f€", transactionValue);
您可以看到它按字面意思使用了可观察字段,而我认为是因为String.format
的签名是(String string, Object args...)
。因为可观察字段是Object
,所以它可以按原样使用,因此代码生成器不会尝试&#34;得到&#34;而是双值。
日期格式设置示例有效,因为format
方法的签名为(Date date)
。因此,代码生成器意识到签名不匹配,但是可观察类型确实如此,因此它为您提供了它,并且您将看到类似这样的内容:
java.util.Date transactionDateGet = null;
// read transaction.date.get()
transactionDateGet = transactionDate.get();
androidTextFormatDateFormatGetDateFormatContextFormatTransactionDate =
android.text.format.DateFormat.getDateFormat(
getRoot().getContext()).format(transactionDateGet);
正如您已经指出的那样,最简单的方法就是在绑定中手动调用.get()
。但是,正如@elmorabea指出的那样,我建议避免在XML中使用逻辑。相反,我建议使用封装显示逻辑的视图模型:
public class TransactionViewModel {
private final Transaction mTransaction;
public TransactionViewModel(@NonNull Transaction transaction) {
mTransaction = transaction;
}
@Bindable
public String getTransactionValueText() {
return String.format("%.2f€", transaction.getValue());
}
}
然后你有这样的事情:
android:text='@{viewModel.transactionValueText}'
这是更多的工作,因为你必须为每个布局文件增加一个类;您必须将可观察字段从模型移动到视图模型;并且您必须使您的视图模型注意模型以将更改传播到视图,但关注点的分离使得从长远来看更容易更新,扩展,重用和维护。
希望有所帮助!