![](/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.