2016-05-26 14 views
5

Tôi phải thiếu cái gì đó ở đây. Mỗi ví dụ tôi đã thấy với liên kết 2 chiều của Android được dựa trên String trong dữ liệu sao lưu cho bất kỳ điều gì mà người dùng có thể nhập, chẳng hạn như EditText.Cách đúng số 2-ràng buộc số cho Android editText

Xử lý mọi thứ không phải là Chuỗi có vẻ hơi ... không phù hợp. Ví dụ, nếu tôi có một đôi trong mô hình miền của tôi cần phải chỉnh sửa được, thì ràng buộc tốt nhất mà tôi đã đưa ra yêu cầu là ViewModel với rất nhiều mã để giao tiếp giữa mô hình và EditText.

Tôi có thiếu khóa nào không? Tôi có thực sự cần 30 dòng mã để giao diện một số EditText với số tăng gấp đôi không? Vì mục đích của cuộc thảo luận, chúng ta hãy xem xét một lĩnh vực tiền tệ, thể hiện dưới dạng một đôi, trong một hai chiều ràng buộc EditText:

<EditText 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:inputType="numberDecimal" 
android:text="@={fragModel.startBucks}" 
android:id="@+id/editText2"/> 

và đây là ViewModel Tôi đã có để xây dựng nhằm cung cấp cho các EditText một chuỗi để liên kết với.

@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); 
} 

Ở đây, tôi đã viết a simple, compilable example of 2-way binding with a ViewModel. Nó minh họa những khó khăn mà tôi đã liên tục cập nhật một phao trong mô hình miền - cuối cùng, tôi quyết định không có cách nào để làm điều đó mà không cần viết một TextWatcher tùy chỉnh cho mỗi lĩnh vực tên miền.

Trả lời

1

Cách tiếp cận của tôi là trì hoãn phương thức callingPropertyChanged bằng cách sử dụng Handles. Bằng cách này trong khi người dùng đang gõ, mã không chạy, sau đó 2,5 giây sau khi người dùng đã dừng lại để nhập ký tự cuối cùng, notificationPropertyChanged sẽ được gọi.

Hiệu ứng hình ảnh rất thú vị và người dùng được tự do viết số điện thoại tùy thích.

Xem hai ví dụ này:

Sử dụng có thể sử dụng nhỏ gọn mã này cho từng lĩnh vực (?):

// 
// 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); 
} 

Mã này thay vào đó là hữu ích khi bạn sử dụng chuyển đổi tiền tệ hoặc phần trăm chuyển đổi. Người dùng có thể viết một đồng bằng kép, mã chuyển đổi thành chuỗi tiền tệ. Nếu setter được gọi với chuỗi tiền tệ, mã có thể chuyển đổi nó thành gấp đôi.

// 
// 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); 
} 
+0

Cảm ơn! Đó là một ví dụ hữu ích và thực tế, và có lẽ không có cách nào tốt hơn. Tuy nhiên, những gì tôi thực sự tìm kiếm là một cách thanh lịch và đơn giản để ràng buộc một phao vào một trường có mã tối thiểu. Nó có vẻ lạ với tôi rằng nó rất đơn giản để ràng buộc một chuỗi và rất phức tạp để ràng buộc một phao. –

Các vấn đề liên quan