2016-03-07 154 views
1

爲什麼不能在android數據綁定庫中定義通用綁定轉換?通用@綁定轉換不起作用

@BindingConversion 
public static <T> T convertMyClass(MyClass<T> obj) { 
    return obj.get(); 
} 

使用此方法我得到can not find the setter for attribute 'android:text' with parameter type com.example.MyClass<java.lang.String>錯誤。定義明確的類型工作正常。

我試圖找到方式ObservableField<T>正在轉換,但沒有成功。有誰知道這是怎麼發生的?有什麼我做錯了嗎?

回答

2

用兩個詞:type erasure

泛型是一把雙刃劍,它可以削減類型系統的一些運行時間能力,以換取編譯時間檢查。您正在告訴編譯器重寫代碼以使這些類型轉換「正常工作」。權衡是它必須將泛型類引用(如「T」)轉換爲「Object」。因此,編譯後您的方法的簽名是

Object convertMyClass(MyClass) 

數據綁定系統正在查找返回類型「字符串」。所以甚至不考慮你的方法。

數據綁定系統可能會變得更聰明,能夠識別您的BindingConversion,但我不會屏住呼吸的功能。

下面是一些說明類型擦除的bash。

$ echo 'public class A{ public <T> T deRef(java.util.concurrent.atomic.AtomicReference<T> atom) {return atom.get();} }' >A.java 
$ javac A.java 
$ groovy -e 'println A.class.getMethod("deRef", java.util.concurrent.atomic.AtomicReference.class)' 
public java.lang.Object A.deRef(java.util.concurrent.atomic.AtomicReference) 

最後一行輸出是通用方法的方法簽名。

一個變通辦法將與特定參數的子類的子類MyClass的,像這樣:

public class MyStringClass extends MyClass<String> { 
    @Override 
    public String get() { 
    return super.get(); 
    } 
    @BindingConversion 
    public static String convertMyClass(MyStringClass obj) { 
    return obj.get(); 
    } 
} 

關於ObservableField,它不需要BindingConversion機制,因爲數據綁定庫引用它在Java代碼,因此編譯時泛型檢查完成匹配類型的工作。

+0

您是否想過使用此方法的任何解決方法? – Bolein95

+0

@ Bolein95我用解決方法更新了它。那對你有用嗎? –

+0

它沒有。泛泛主義丟失了。無論如何,你的答案解釋了這個問題。好像我必須將此報告給數據綁定社區。 – Bolein95