如果我理解正確的,我們假定你是以下幾點:
import kotlinx.android.synthetic.main.activity_main.item_test
import kotlinx.android.synthetic.main.activity_main.item_test_2
class MyClass {
lateinit var x: View
lateinit var y: View
fun foo() {
val foo1 = x.item_test // Compiles
val foo2 = y.item_test // Compiles as well
val bar1 = x.item_test_2 // Compiles too
val bar2 = y.item_test_2 // Compiles yet again
}
}
所以,在我看來,這是類型查看任何屬性將有一個合成導入相關的綜合性能,無論是否它是否有效。因此,擴展實現看起來是蠻力的,如果有什麼錯誤的話,不會提醒開發人員。
這是正確的。現在
,所述item_test
進口基本上在View
類的擴展屬性(簡化的示例[1]):
val View.item_test get() = findViewById(R.id.item_test)
對於每個在佈局的意見,該插件生成這些特性,並提出他們在他們的相關文件中。這些屬性也存在於Activity
和Fragment
。
因此,當您撥打x.item_test
時,您基本上呼叫x.findViewById(R.id.item_test)
[1]。
編譯後,插件將這些調用替換回findViewById
。所以上面的方案的簡化的反編譯版本[1](在Java中):
final class MyClass {
public View x;
public View y;
public final void foo() {
TextView foo1 = (TextView) x.findViewById(id.item_test);
TextView foo2 = (TextView) y.findViewById(id.item_test);
TextView bar1 = (TextView) x.findViewById(id.item_test_2);
TextView bar2 = (TextView) y.findViewById(id.item_test_2);
}
}
由於這只是上View
一個擴展函數時,不存在完整性檢查,以檢查是否存在於視圖層次item_test
x
或y
,就像他們不存在findViewById
一樣。如果findViewById
呼叫返回null
,則值爲null
或KotlinNullPointerException
被引發。
- 加法佈局視圖id的作爲屬性被盲目地進行。任何由這樣的綜合導入暗示的視圖id都被添加到View類型的任何屬性(或View的子類)中。這包括由類繼承的這種類型的屬性。
是,由於屬性是基於View
一個擴展特性,如上所述。
- 由於屬性被盲目地加入它是在所述顯影劑有責任確保相應於合成進口運行時視圖被訪問的合成屬性之前或分配一個異常將被拋出。
我不確定你在問什麼。如果你的意思是你在調用x.item_test
之前必須初始化x
,那就對了。另外,x
的層次結構中應該有一個視圖item_test
。
- 如果在一個文件中指定了兩個或多個這樣的導入,那麼它們的view id的聯合會被盲目地添加到View類型的所有類屬性中。 允許多次導入的目的是解釋一個佈局文件包含另一個佈局文件的情況。
是的。
[1]:其實,在幕後這些查找被緩存。請參閱文檔中的Under the hood。
@roobyroo我對你的問題作了另一種解釋,這是否更好? – nhaarman
我已經按照承諾回覆了這個問題。 – roobyroo
@roobyroo請參閱答案的補充。 – nhaarman