最近对GMS任务库进行了@Nullable更改。反编译的.class的前几行看起来像
public abstract class Task<TResult> {
public Task() {
}
public abstract boolean isComplete();
public abstract boolean isSuccessful();
public abstract boolean isCanceled();
@Nullable
public abstract TResult getResult();
以前我的Kotlin代码已编译:
if (task.isSuccessful) {
task.result.user?.getIdToken(false)?.addOnCompleteListener { taskk ->
this.emailIdTokenCompleteListener()(taskk)
}
在更新了一些gms play-services-zzz
依赖关系之后,代码现在具有编译错误:
LoginActivity.kt:(148,28):在AuthResult类型的可为空的接收器上仅允许安全(?。)或非空声明(!!。)调用?
问题是,isSuccessful() == true
是否暗示着getResult != null
?还是将if测试更改为if (task.result != null)
会更好?
答案 0 :(得分:1)
您看到的是Kotlin编译器无法基于isSuccessful的结果将结果智能广播到NonNull类型,这可能在与Java和Kotlin代码交互时发生。
在Kotlin 1.3中,该语言中添加了“合同”的实现,以允许开发人员以IDE可以用来静态分析和推断类型(智能广播)的格式添加有关方法的元数据。
请参见第1.2节“返回和暗示” https://proandroiddev.com/kotlin-contracts-make-great-deals-with-the-compiler-f524e57f11c
因此,使用合同,如果实现如下所示,它将可以正确进行智能广播:
open class Task<T> {
var result: T? = null
private set
fun isSuccessful(): Boolean {
contract {
returns(true) implies (result != null)
}
return result != null
}
}
但是,在您的情况下,您可能想抛出另一个安全的呼叫操作员?
,并使用Elvis操作员!task.isSuccessful
来调用?:
代码,如下所示:
if (task.isSuccessful) {
task.result?.user?.getIdToken(false)?.addOnCompleteListener { taskk ->
this.emailIdTokenCompleteListener()(taskk)
} ?: handleFailure() // Defensively call just in case
} else {
handleFailure()
}