Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android LiveData ObserveForver不工作_Android_Kotlin_Dagger 2_Android Livedata - Fatal编程技术网

Android LiveData ObserveForver不工作

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

我有一个WeatherRepository类,它调用WeatherProvider类开始获取天气

成功获取天气后,我只需使用postValue函数发布天气,但WeatherRepository类的init块中的livedata上的观察者从未被调用

我很困惑,因为我错过了什么

任何见解都会非常有用

以下是我的存储库和提供程序代码:

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查看我的项目。