![](/img/trans.png)
[英]ViewBinding vs Kotlin Android Extensions with synthetic views
[英]Kotlin views with synthetic binding and nullability
我注意到當使用 Kotlin 的合成綁定時,返回的視圖是非空的(Kotlin 將返回View!
)。 但這對我來說意義不大,因為findCachedViewById
實際上可以返回空結果,這意味着視圖實際上可以為空。
public View _$_findCachedViewById(int var1) {
if(this._$_findViewCache == null) {
this._$_findViewCache = new HashMap();
}
View var2 = (View)this._$_findViewCache.get(Integer.valueOf(var1));
if(var2 == null) {
View var10000 = this.getView();
if(var10000 == null) {
return null;
}
var2 = var10000.findViewById(var1);
this._$_findViewCache.put(Integer.valueOf(var1), var2);
}
return var2;
}
那么為什么在這種情況下它們不是可選的呢? 為什么 Kotlin 不直接返回View?
使用合成綁定時,開發人員在處理視圖時將被迫檢查可空性?
也許這只是因為我是 Kotlin 的新手,但我認為這有點違反直覺,因為變量不是可選的,但我們仍然應該檢查視圖是否實際上不為空。
那么在這種情況下,像下面的代碼那樣做有意義嗎?
view?.let {
// handle non null view here
}
我想通了,我總是在發布我的問題后立即找到正確的 SO 問題:)
View
后面的單個感嘆號實際上並不意味着視圖不能像我預期的那樣為 null。
This answer to another question基本上回答了我的確切問題。 View
在使用合成綁定時實際上可以為 null,但我們無法確定,因此只有一個感嘆號。
因此,可以安全地假設我在上面發布的代碼 - 使用?.let{...}
是處理視圖的完全可接受的方式,當您不確定它們在訪問它們時是否已經初始化時。
視圖可能為空的情況非常罕見,但它可能會發生。
正如您已經指出的那樣,單個感嘆號並不意味着它不是空的,而是它是一種 Java 平台類型,編譯器不知道它是否可以為空。
我認為你的建議很好,盡管它在 null 的實際情況下默默地失敗了,這實際上可能不是你想要的。
假設您試圖在 onCreateView 中調用您的視圖,但忘記了它尚未初始化。 該片段不會按預期運行,但不會產生有意義的錯誤來幫助您調試問題。
我仍在嘗試自己解決一個或另一個解決方案,但我建議要么顯式處理 null 的情況:
view?.let {
//...
} ?: throwExceptionIfDebugElseLogToCrashlytics()
或者決定這次你真的希望它拋出 NullPointerException 在這種情況下我建議:
view!!.let {
//...
}
后者不會因為“應該”是不可能的邊緣情況而使您的代碼膨脹,並且它不會悄無聲息地失敗,但它仍然讓讀者清楚地知道視圖可能為空。 顯然,。 編譯器不需要,它只是為了使處理平台類型的選擇策略更加明確。
如果您嘗試在活動或視圖的上下文之外或在 lambda 中從偵聽器訪問視圖,則合成視圖綁定實際上可能會發生空指針異常。
問題出在 lambda 中,Frantisek 在這里發布了相關信息:https ://stackoverflow.com/posts/comments/115183445?noredirect=1
這個想法是 Android 中的 xml 布局是相當靜態的,為了使用合成視圖,您必須創建一個已解析布局的直接導入:
import kotlinx.android.synthetic.main.activity_main.*
因此,在現實生活中,不存在View
為空的非魔法場景。 除非你選擇了錯誤的合成布局,否則你會在第一次運行時崩潰。
也就是說,如果您在運行時修改視圖、刪除Views
等,它當然會中斷。但同樣,這不是合成Views
的默認用法,需要不同的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.