Aut*_*umn 6 android android-databinding
我必须在这里遗漏一些东西.我在Android的双向绑定中看到的每个例子都基于String用户可输入的任何内容的支持数据,例如EditText.
处理任何不是字符串的东西似乎有点......不优雅.例如,如果我的域模型中有一个需要可编辑的双,那么我提出的最好的绑定需要一个ViewModel令人惊讶的很多代码来连接模型和模型EditText.
我错过了什么关键吗?我真的需要30行代码才能EditText与双重接口吗?为了便于讨论,让我们考虑一个货币字段,以双向方式表示为双向EditText:
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:text="@={fragModel.startBucks}"
android:id="@+id/editText2"/>
Run Code Online (Sandbox Code Playgroud)
这里是我必须构造的ViewModel,以便为EditText提供一个绑定的字符串.
@Bindable private String startBucksString;
private double localBucks;
public String getStartBucksString() {
double domainBucks = cd.getStartBucks();
// Ignore incoming change of less than rounding error
if( Math.abs(localBucks - domainBucks) < .001 ) return startBucksString;
startBucksString = "";
if( domainBucks != 0)
startBucksString = String.format("$%.2f", domainBucks);
return startBucksString;
}
public void setStartBucksString(String inBuckstr) {
double calcBucks=0;
inBuckstr = inBuckstr.replaceAll( "[^\\d.]", "" );
try {
calcBucks = Double.parseDouble(inBuckstr);
} catch( NumberFormatException e) {
return;
}
// Neglect outgoing change of less than rounding error
if( Math.abs(localBucks - calcBucks) < .001 ) return;
startBucksString = String.format("$%.2f", calcBucks);
localBucks = calcBucks;
cd.setStartBucks(calcBucks);
notifyPropertyChanged(BR.startBucksString);
}
Run Code Online (Sandbox Code Playgroud)
在这里,我编写了一个简单,可编译的与ViewModel进行双向绑定的示例.它说明了我在连续更新域模型中的浮点数时遇到的困难 - 最后,我决定如果不为每个域字段编写自定义TextWatcher,就无法做到这一点.
我的方法是使用句柄延迟调用notifyPropertyChanged 方法。这样,当用户键入时,代码不会运行,然后在用户停止键入最后一个字符后 2.5 秒,将调用 notificationPropertyChanged。
视觉效果炫酷,用户可以随意书写数字。
看这两个例子:
使用可以对每个字段使用这个紧凑(?)代码:
//
// g1FuelCostYear field
//
private double g1FuelCostYear;
@Bindable
public String getG1FuelCostYear() {
return Double.valueOf(g1FuelCostYear).toString();
}
private Handler hG1FuelCostYearDelay = null;
public void setG1FuelCostYear(String g1FuelCostYear) {
// Delayed notification hadler creation
if (hG1FuelCostYearDelay == null) {
hG1FuelCostYearDelay = new Handler() {
@Override
public void handleMessage(Message msg) {
notifyPropertyChanged(it.techgest.airetcc2.BR.g1FuelCostYear);
}
};
} else {
// For each call remove pending notifications
hG1FuelCostYearDelay.removeCallbacksAndMessages(null);
}
// Data conversion logic
try {
this.g1FuelCostYear = Double.parseDouble(g1FuelCostYear);
}
catch (Exception ex) {
this.g1FuelCostYear = 0.0;
log(ex);
}
// New delayed field notification (other old notifications are removed before)
hG1FuelCostYearDelay.sendEmptyMessageDelayed(0,2500);
}
Run Code Online (Sandbox Code Playgroud)
当您使用货币转换器或百分比转换器时,此代码非常有用。用户可以编写一个普通的双精度数,代码转换为货币字符串。如果使用货币字符串调用设置器,代码也可以将其转换为双精度。
//
// g1FuelCostYear field
//
private double g1FuelCostYear;
@Bindable
public String getG1FuelCostYear() {
NumberFormat nf = NumberFormat.getCurrencyInstance();
return nf.format(this.g1FuelCostYear);
//return Double.valueOf(g1FuelCostYear).toString();
}
private Handler hG1FuelCostYearDelay = null;
public void setG1FuelCostYear(String g1FuelCostYear) {
if (hG1FuelCostYearDelay == null)
{
hG1FuelCostYearDelay = new Handler() {
@Override
public void handleMessage(Message msg) {
notifyPropertyChanged(it.techgest.airetcc2.BR.g1FuelCostYear);
}
};
} else {
hG1FuelCostYearDelay.removeCallbacksAndMessages(null);
}
boolean success = false;
try {
NumberFormat nf = NumberFormat.getCurrencyInstance();
this.g1FuelCostYear = nf.parse(g1FuelCostYear).doubleValue();
success = true;
}
catch (Exception ex) {
this.g1FuelCostYear = 0.0;
log(ex);
}
if (!success) {
try {
this.g1FuelCostYear = Double.parseDouble(g1FuelCostYear);
success = true;
} catch (Exception ex) {
this.g1FuelCostYear = 0.0;
log(ex);
}
}
updateG1FuelConsumption();
hG1FuelCostYearDelay.sendEmptyMessageDelayed(0,2500);
}
Run Code Online (Sandbox Code Playgroud)