基礎(chǔ)知識(shí)
-
在 Kotlin 中细卧,其類(lèi)型系統(tǒng)嚴(yán)格區(qū)分一個(gè)引用是否可以容納null尉桩。也就是說(shuō),一個(gè)變量是否可空必須顯示聲明酒甸,對(duì)于可空變量魄健,在訪(fǎng)問(wèn)其成員時(shí)必須做空處理,否則無(wú)法編譯通過(guò)插勤。
var a: String = "abc" a = null // 編譯錯(cuò)誤 var b: String? = "abc" //String? 表示該 String 類(lèi)型變量可為空 b = null // 編譯通過(guò)
-
盡管當(dāng)前kotlin在android項(xiàng)目開(kāi)發(fā)中占比在逐步提高沽瘦,但是大量開(kāi)發(fā)還是Java代碼。供應(yīng)用層調(diào)用的framework代碼也是java實(shí)現(xiàn)的农尖,所以大量情景下是kotlin和java代碼混合開(kāi)發(fā)的析恋。那當(dāng)kotlin調(diào)用Java代碼,Java代碼是如何定義是否能容納null呢盛卡?
//不為空 @NonNull public final Context requireContext() { Context context = getContext(); if (context == null) { throw new IllegalStateException("Fragment " + this + " not attached to a context."); } return context; } //可為空 @Nullable public Context getContext() { return mHost == null ? null : mHost.getContext(); }
函數(shù)參數(shù)是否容納null判斷也是同理用@Nullable和@NonNull標(biāo)記
問(wèn)題
-
最近將compileSdkVersion助隧、targetSdkVersion更新到27,然后收到了些編譯錯(cuò)誤滑沧,例如:context is now nullable(context?) instead of non-null, 特別在fragment中的getActivity(),fragmentManager等都有編譯報(bào)錯(cuò)并村,扒了下代碼查找報(bào)錯(cuò)的問(wèn)題
//報(bào)錯(cuò) tpye mismatch required:context found:context? val viewDialog = AlertDialog.Builder(context) //context參數(shù)要求為 @NonNull public Builder(@NonNull Context context) { this(context, resolveDialogTheme(context, 0)); }
//返回的context為 Nullable
@Nullable
public Context getContext() {
return mHost == null ? null : mHost.getContext();
}
```
邊緣報(bào)錯(cuò)的原因應(yīng)該一目了然了。
解決
-
直接告訴變壓器context不可能為null滓技,編譯時(shí)候不去null檢查哩牍。嗯,現(xiàn)在編譯是不報(bào)錯(cuò)了令漂,當(dāng)然造成結(jié)果就是一旦為null直接掛了膝昆。而且既然API寫(xiě)的是Nullable丸边,那就是存在為null的情況的
builder = AlertDialog.Builder(context!!)
-
這個(gè)是在網(wǎng)上看到的解決方案,大概就是在basefragment中重寫(xiě)getContext()方法荚孵,跟1換湯不換藥妹窖。
override fun getContext(): Context { return super.getContext()!!
}
```
-
其實(shí)APi27中新加了requireContext()方法,類(lèi)似還有requireActivity()收叶,requireHost()方法
@NonNull public final Context requireContext() { Context context = getContext(); if (context == null) { throw new IllegalStateException("Fragment " + this + " not attached to a context."); } return context; }
}
```