Kotlin LiveData和协同程序-属性必须初始化或抽象
我正试图在MVVM中同时使用LiveData和协同程序,但我可能缺少一些简单的东西Kotlin LiveData和协同程序-属性必须初始化或抽象,kotlin,coroutine,android-livedata,kotlin-coroutines,Kotlin,Coroutine,Android Livedata,Kotlin Coroutines,我正试图在MVVM中同时使用LiveData和协同程序,但我可能缺少一些简单的东西 class WeatherViewModel ( private val weatherRepository: ForecastRepository ) : ViewModel() { var weather: LiveData<Weather>; /** * Cancel all coroutines when the ViewModel is cleared.
class WeatherViewModel (
private val weatherRepository: ForecastRepository
) : ViewModel() {
var weather: LiveData<Weather>;
/**
* Cancel all coroutines when the ViewModel is cleared.
*/
@ExperimentalCoroutinesApi
override fun onCleared() {
super.onCleared()
viewModelScope.cancel()
}
init {
viewModelScope.launch {
weather = weatherRepository.getWeather()
}
}
}
如何解决此问题?更改签名如下:
var weather = MutableLiveData<Weather>();
var weather=MutableLiveData();
另外,您应该只返回一个Weather
对象,而不是LiveData
因此,您应该更改
getWeather()
的签名以返回:Weather
Weather
必须使用类的实例化进行初始化,因为您没有说过它可以为null,并且您没有使用lateinit
关键字(在本例中不应该使用该关键字)
launch
是一个异步协同路由调用,它会立即返回,但会在将来的某个时间执行。这意味着您的init
块在未初始化weather
的情况下完成并返回
改用runBlocking
。这将一直阻止,直到您在init
块中得到结果,从而保证weather在实例化时不为null。比如:
init {
weather = runBlocking {
weatherRepository.getWeather()
}
}
您还可以将哪个协同路由上下文调度器传递给运行阻塞
或-坚持使用协同程序,但加入init块,如:
init {
val job = viewModelScope.launch {
weather = weatherRepository.getWeather()
}
job.join()
}
您可以将weather
属性声明为:
private lateinit var weather:LiveData
或者让它成为:
private var weather: LiveData<String>? = null
private-var-weather:LiveData?=无效的
如果您确定在首次使用该属性之前将对其进行初始化,请使用lateinit
,否则在Kotlin中将其设置为可空,默认情况下,每个属性都必须初始化(即使是带有null的可空类型)
您可以直接在声明中或在init块中初始化属性
代码的问题在于,init块完成后,启动函数可以继续运行,编译器知道这一点。所以,它告诉你——不要指望它
如前所述,您可以使用lateinit声明稍后将初始化您的属性,前提是您确定它将在您使用它之前发生。这听起来不太正确。这意味着我将把Weather
对象分配给MutableLiveData
。我只需要存储库中提供的LiveData
房间或改装。不,您会将房间或改装提供的天气对象指定给Weather.value
,但从LiveData
中取出值并将其放入MutableLiveData
将无法使用LiveData
。我正在使用数据绑定,希望值随着值的更改而自动更新。您应该以这种方式使用LiveData
进行视图更新,不适用于ViewModel/Presenter--Room/Refundation InteractionMain线程在使用此方法返回之前不会被阻止吗?@Alan该类实例化的线程将被阻止,直到对象被实例化(包括其所有非空变量)。对如果您想立即返回并将weather
类型设置为LiveData?
,并在稍后的某个阶段将字段设置为fine,但我怀疑在设置该变量之前它是无用的,然后每次使用它时都必须进行空检查。Kotlin是空安全的。@Alan您正在尝试执行冲突的操作-拥有一个不为空的变量,并在构建对象时异步实例化它。如果weatherRepository.getWeather()
不是必须在协同程序上下文中调用的挂起函数,则只需执行weather=weatherRepository.getWeather()
。我的理解是,在拥有该实例之前,您的类不能做任何它需要做的事情。
private lateinit var weather: LiveData<String>
private var weather: LiveData<String>? = null