Kotlin 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.

我正试图在MVVM中同时使用LiveData和协同程序,但我可能缺少一些简单的东西

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