job.cancel():取消job,执行后该job就进入cancelling状态,但是否真的取消了需要看job自身实现。Coroutine标准库中定义的 suspend function 都是支持取消操作的(比如 delay)。自定义job的时候可以通过 isActive 属性来判断当前任务是否被取消了,如果发现被取消了则停止继续执行。如果自定义job没有相应的处理逻辑,那么就算调用job.cancel(),也并不能取消它的执行。
SupervisorJob(parent: Job? = null):返回一个job实例,里面的子Job不相互影响,一个子Job失败了,不影响其他子Job的执行。parent参数用于关联自己本身的父job。如果研究协程源码的话,会常看到ContextScope(SupervisorJob() + Dispatchers.Main)的写法(如ViewModel.viewModelScope的实现),这里的 + 号是CoroutineContext对操作符plus的重载,前后两者都是CoroutineContext的子类。
后记拾遗当使用公有属性时,有时会抛出“Smartcast is impossible because propery has open or custom getter”的编译时错误,究其原因是编译器分析代码发现每次get属性时返回的对象可能不是同一个。解决方法很简单,只要定义一个临时变量指向某次get获得的值即可。可参看Smartcast is impossible because propery has open or custom getter
Java泛型擦除导致的问题。如下代码可正常运行:
private fun getToken(): Token? { val preference = TaoismApplication.appContext.sharedPreferences(SharedPreference.SESSION) val json = preference.getString(SharedPreference.TOKEN, "") if (!json.isNullOrBlank()) { return Gson().fromJson<Token>(json, object : TypeToken<Token>() {}.type) } else { return null } }由于代码中有较多getXXX(),抽取模板代码:
private fun <T : Any?> get(key: String): T? { val preference = TaoismApplication.appContext.sharedPreferences(SharedPreference.SESSION) val json = preference.getString(key, "") if (!json.isNullOrBlank()) { return Gson().fromJson<T>(json, object : TypeToken<T>() {}.type) } else { return null } }调用get<Token>(SharedPreference.TOKEN)报错:java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.xxx.xxx.Token。
so,只能将类型信息显式传入,改造方法签名为get(key: String, typeToken: Type)。
kotlin异常:Kotlin 的异常都是 Unchecked exception。若在函数上注解了@Throws,则编译成Java代码会变成符合Java模式的checked exception,即在方法定义上会显式声明可能抛出的异常类型,需要在调用链路上处理。
使用intellij idea进行kotlin和java混合开发,最好将kotlin文件和java文件分各自文件夹存放,否则运行时可能会报找不到类的错误(因为编译时会将不是属于该文件夹的且没有被其它文件引用的代码文件忽略)。如下:
Kotlin协程 —— 今天说说 launch 与 async