Android LiveData ObserveForver不工作
我有一个WeatherRepository类,它调用WeatherProvider类开始获取天气 成功获取天气后,我只需使用postValue函数发布天气,但WeatherRepository类的init块中的livedata上的观察者从未被调用 我很困惑,因为我错过了什么 任何见解都会非常有用 以下是我的存储库和提供程序代码:Android LiveData ObserveForver不工作,android,kotlin,dagger-2,android-livedata,Android,Kotlin,Dagger 2,Android Livedata,我有一个WeatherRepository类,它调用WeatherProvider类开始获取天气 成功获取天气后,我只需使用postValue函数发布天气,但WeatherRepository类的init块中的livedata上的观察者从未被调用 我很困惑,因为我错过了什么 任何见解都会非常有用 以下是我的存储库和提供程序代码: class WeatherRepository @Inject constructor(private var weatherDao: WeatherDao, priv
class WeatherRepository @Inject constructor(private var weatherDao: WeatherDao, private var weatherProvider: WeatherProvider) {
private fun startFetchWeatherService() {
weatherProvider.startFetchWeatherService()
}
init {
// Control flow always gets to this point
var weather = weatherProvider.getDownloadedWeather()
weather.observeForever { // This observer never gets called
if (it != null) AsyncTask.execute { insertWeather(it) }
}
if (isFetchNeeded()) {
startFetchWeatherService() // Android Studio always execute this line since no data is inserted by observer and fetch is needed
}
}
....
}
class WeatherProvider(private val context: Context) {
private val mDownloadedWeather = MutableLiveData<List<Weather>>()
...
fun getDownloadedWeather(): MutableLiveData<List<Weather>> = mDownloadedWeather
fun getFromInternet() {
...
call.enqueue(object : Callback<WorldWeatherOnline> {
override fun onFailure(call: Call<WorldWeatherOnline>?, t: Throwable?) {} // TODO show error
override fun onResponse(call: Call<WorldWeatherOnline>?, response: Response<WorldWeatherOnline>?) {
if (response != null) {
val weather = response.body()?.data
if (weather != null) {
mDownloadedWeather.postValue(WeatherUtils.extractValues(weather)) // app always gets to this point and WeatherUtils successfully returns the List of weathers full of data
}
}
}
})
}
fun startFetchWeatherService() {
val intentToFetch = Intent(context, WeatherSyncIntentService::class.java)
context.startService(intentToFetch)
}
}
...
// Dependency injection always works
// Here's my dagger2 module (other modules are very simillar to this one)
@Module
class ApplicationModule(private val weatherApplication: WeatherApplication) {
@Provides
internal fun provideWeatherApplication(): WeatherApplication {
return weatherApplication
}
@Provides
internal fun provideApplication(): Application {
return weatherApplication
}
@Provides
@Singleton
internal fun provideWeatherProvider(context: WeatherApplication): WeatherProvider {
return WeatherProvider(context)
}
}
@Singleton
class CustomViewModelFactory constructor(private val weatherRepository: WeatherRepository, private val checklistRepository: ChecklistRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
when {
modelClass.isAssignableFrom(WeatherViewModel::class.java) ->
return WeatherViewModel(weatherRepository) as T
modelClass.isAssignableFrom(ChecklistViewModel::class.java) ->
return ChecklistViewModel(checklistRepository) as T
else ->
throw IllegalArgumentException("ViewModel Not Found")
}
}
}
class WeatherFragment : Fragment() {
private lateinit var mWeatherModel: WeatherViewModel
@Inject
internal lateinit var viewModelFactory: ViewModelProvider.Factory
....
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
mWeatherModel = ViewModelProviders.of(this, viewModelFactory)
.get(WeatherViewModel::class.java)
...
}
}
class WeatherRepository@Inject构造函数(私有变量weatherDao:weatherDao,私有变量weatherProvider:weatherProvider){
私人娱乐启动服务(){
weatherProvider.startFetchWeatherService()的
}
初始化{
//控制流总是到达这一点
var weather=weatherProvider.getDownloadedWeather()
weather.observeforviever{//此观察者从未被调用
如果(it!=null)AsyncTask.execute{insertWeather(it)}
}
if(isFetchNeeded()){
startFetchWeatherService()//Android Studio始终执行这一行,因为观察者不插入任何数据,并且需要获取
}
}
....
}
类WeatherProvider(专用val上下文:上下文){
private val mDownloadedWeather=MutableLiveData()
...
fun getDownloadedWeather():MutableLiveData=mDownloadedWeather
乐趣来自互联网{
...
排队(对象:Callback{
override-fun-onFailure(调用:调用?、t:Throwable?{}//TODO显示错误
覆盖fun onResponse(调用:调用?,响应:响应?){
if(响应!=null){
val weather=响应.body()?.data
如果(天气!=null){
mDownloadedWeather.postValue(WeatherUtils.extractValues(weather))//应用程序总是到达这一点,WeatherUtils成功返回充满数据的天气列表
}
}
}
})
}
有趣的startFetchWeatherService(){
val intentotfetch=Intent(上下文,WeatherSyncIntentService::class.java)
context.startService(intentFetch)
}
}
...
//依赖注入总是有效的
//这是我的dagger2模块(其他模块与此模块非常相似)
@模块
类应用程序模块(私有val weatherApplication:weatherApplication){
@提供
内部fun ProviderWeatherApplication():WeatherApplication{
返回天气预报应用程序
}
@提供
内部fun ProviderApplication():应用程序{
返回天气预报应用程序
}
@提供
@独生子女
内部fun ProviderWeatherProvider(上下文:WeatherApplication):WeatherProvider{
返回WeatherProvider(上下文)
}
}
@独生子女
类CustomViewModelFactory构造函数(私有val weatherRepository:weatherRepository,私有val checklistRepository:checklistRepository):ViewModelProvider.Factory{
重写趣味创建(modelClass:Class):T{
什么时候{
modelClass.isAssignableFrom(WeatherViewModel::class.java)->
将WeatherViewModel(weatherRepository)返回为T
modelClass.isAssignableFrom(ChecklistViewModel::class.java)->
将ChecklistViewModel(checklistRepository)返回为T
其他->
抛出IllegalArgumentException(“未找到ViewModel”)
}
}
}
类WeatherFragment:Fragment(){
私有lateinit var mWeatherModel:WeatherViewModel
@注入
内部lateinit var viewModelFactory:ViewModelProvider.Factory
....
覆盖活动创建的乐趣(savedInstanceState:Bundle?){
super.onActivityCreated(savedInstanceState)
mWeatherModel=ViewModelProviders.of(此,viewModelFactory)
.get(WeatherViewModel::class.java)
...
}
}
尝试使用
mDownloadedWeather.setValue(WeatherUtils.extractValues(weather))
而不是
mDownloadedWeather.postValue(WeatherUtils.extractValues(weather))
因为postValue()。因此,如果在主线程中执行以下代码:
liveData.postValue("a");
liveData.setValue("b");
首先设置值“b”,然后主线程将用值“a”覆盖它
如果在主线程执行已发布任务之前多次调用此方法,则只会调度最后一个值。无需将
postValue
更改为setValue
,因为它是在同一线程中完成的。这里真正的问题是Dagger2的设置方式
在WeatherFragment.kt中使用
internal lateinit var viewModelFactory: CustomViewModelFactory
而不是
internal lateinit var viewModelFactory: ViewModelProvider.Factory
还需要在CustomViewModelFactory.kt的构造函数中添加@Inject注释
class CustomViewModelFactory @Inject constructor(
最后,根据您提供的代码,WeatherProvider.kt根本没有处于初始化状态。您可以使用以下代码执行此操作:
init {
getFromInternet()
}
也许你应该在调用
onError
或response.body()
为空时记录一些东西?@EpicPandaForce我已经记录了它,它没有调用该错误方法。它甚至使用了postValue方法。我已经试过调试每一个步骤。@EpicPandaForce如果您想查看整个项目,那么您可以使用TeamViewerHanks查看我的代码库,感谢您的关注,但遗憾的是,您提供的解决方案不起作用。如果需要,可以使用teamviewer查看我的项目。