LiveData和Coroutines - 属性必须初始化或抽象

问题描述 投票:0回答:3

我试图在MVVM中一起使用LiveData和Coroutines,我可能会遗漏一些简单的东西。

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()
        }

    }

}

但我正在让Property must be initialized or be abstractweather函数中分配init。我假设这是因为我使用coroutines viewModelScope.launch

override suspend fun getWeather(): LiveData<Weather> {
    return withContext(IO){
       initWeatherData()
       return@withContext weatherDao.getWeather()
    }
}

我该如何解决?

kotlin coroutine android-livedata kotlin-coroutines
3个回答
0
投票

更改签名如下:

var weather =  MutableLiveData<Weather>();

另外,你应该只返回一个Weather对象而不是LiveData <>所以你应该改变getWeather()的签名来返回: Weather


0
投票

您可以将weather属性声明为lateinit

private lateinit var weather: LiveData<String>

或者让它成为nullable

private var weather: LiveData<String>? = null

如果您确定在首次使用之前初始化该属性,请使用lateinit,否则将其置为可空。


-1
投票

必须使用类的实例化来初始化weather,因为您没有说它可以为null,并且您没有使用lateinit关键字(在这种情况下您不应该使用它)。

launch是一个异步协程调用,它会立即返回,但将来会在某个时刻执行。这意味着你的init块完成并返回而没有初始化weather

请改用runBlocking。这将阻塞,直到您在init块中得到结果,因此保证实例化时天气不为空。就像是:

init {
    weather = runBlocking {
        weatherRepository.getWeather()
    }
}

您也可以将哪个coroutine上下文调度程序传递给runBlocking

或者 - 坚持协程,但加入init块,如:

init {
    val job = viewModelScope.launch {
        weather = weatherRepository.getWeather()
    }
    job.join()
} 
© www.soinside.com 2019 - 2024. All rights reserved.