如何格式化ObservableField(double)DataBinding?

时间:2017-12-03 20:35:20

标签: android android-databinding

所以,我有一个非常简单的问题,我似乎无法在数据绑定中格式化来自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

1 个答案:

答案 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}'

这是更多的工作,因为你必须为每个布局文件增加一个类;您必须将可观察字段从模型移动到视图模型;并且您必须使您的视图模型注意模型以将更改传播到视图,但关注点的分离使得从长远来看更容易更新,扩展,重用和维护。

希望有所帮助!