android - LiveData 观察永远不工作

标签 android kotlin dagger-2 android-livedata

我有一个 WeatherRepository 类,它调用 Wea​​therProvider 类来开始获取天气。

成功获取天气后,我只需使用 postValue 函数发布该天气,但 WeatherRepository 类的 init block 中该实时数据的观察者永远不会被调用。

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

任何见解都会非常有帮助。

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

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

最佳答案

无需将 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()
    }

关于android - LiveData 观察永远不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49670631/

相关文章:

android - 如何使用 GridLayoutManager 删除 RecyclerView 中的行间距

android - 所有 ViewHolders 同时创建

Android UI 测试无法解析 : Intent 的 Activity

java - 使用 Kotlin 在 apk 构建中出现 DuplicateFileException

java - 我无法提供 ViewModel

java - 在 Android 上使用 Dagger2 在某些设备上遇到 VerifyError

android - Dagger2 依赖循环使用@Binds 和@Inject 字段

android - 在点击监听器上设置滑动菜单

java - 操作和编辑 Android app/assets 文件夹中的 Excel 文件

Java Math 类似于 Kotlin 中的类