每次调用Activity的onCreate()时都会调用Repository中的Refresh(不是在屏幕旋转中) [英] Refresh in Repository get called every time onCreate() of Activity called ( not in screen rotation )

查看:167
本文介绍了每次调用Activity的onCreate()时都会调用Repository中的Refresh(不是在屏幕旋转中)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Github中有以下项目: https://github.com/Ali-Rezaei/TVMaze

I have following project in Github : https://github.com/Ali-Rezaei/TVMaze

我已经开始在示例应用程序中将Koin用作依赖项注入框架:

I have started to using Koin as dependency injection framework in a sample app :

class TVMazeApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        startKoin {
            androidContext(this@TVMazeApplication)
            modules(networkModule)
            modules(persistenceModule)
            modules(repositoryModule)
            modules(viewModelModule)
        }
    }
}

这是我的存储库类:

class ShowRepository(
    private val dao: ShowDao,
    private val api: TVMazeService,
    private val context: Context
) {

    /**
     * A list of shows that can be shown on the screen.
     */
    val shows = resultLiveData(
        databaseQuery = {
            Transformations.map(dao.getShows()) {
                it.asDomainModel()
            }
        },
        networkCall = { refreshShows() })

    /**
     * Refresh the shows stored in the offline cache.
     */
    private suspend fun refreshShows(): Result<List<Show>> =
        try {
            if (isNetworkAvailable(context)) {
                val shows = api.fetchShowList().await()
                dao.insertAll(*shows.asDatabaseModel())
                Result.success(shows)
            } else {
                Result.error(context.getString(R.string.failed_internet_msg))
            }
        } catch (err: HttpException) {
            Result.error(context.getString(R.string.failed_loading_msg))
        }
}

还有我的ViewModel:

And my ViewModel :

class MainViewModel(
    repository: ShowRepository
) : ViewModel() {

    private val _shows = repository.shows
    val shows: LiveData<Result<List<Show>>>
        get() = _shows
}

我在Activity中观察到LiveData:

And I observe LiveData in my Activity :

viewModel.shows.observe(this, Observer { result ->
            when (result.status) {
                Result.Status.SUCCESS -> {
                    binding.loadingSpinner.hide() 
                    viewModelAdapter.submitList(result.data)
                }
                Result.Status.LOADING -> binding.loadingSpinner.show()
                Result.Status.ERROR -> {
                    binding.loadingSpinner.hide()
                    Snackbar.make(binding.root, result.message!!, Snackbar.LENGTH_LONG).show()
                }
            }
        })

当我单击后退"按钮时,活动"被销毁(但是应用实例仍然存在,因为我可以从最近的应用访问它).我期望的是在我再次启动应用程序时调用refreshShows()方法,但是它从未被调用.

When I click on Back button, Activity get destroyed ( but instance of app still exist as I can access it from recent apps). What I expect is a call to refreshShows() method when I start the app again, but it never get called.

但是,当我通过清除最近的应用程序并启动该应用程序来破坏该应用程序的实例时,就会调用refreshShows().

But when I destroy instance of app by clearing from recent app and start the app, refreshShows() get called.

每次调用Activity的 onCreate()回调时我该怎么做?

What should I do to have a call on refreshShows() every time onCreate() callback of Activity get called?

fun <T, A> resultLiveData(databaseQuery: () -> LiveData<T>,
                          networkCall: suspend () -> Result<A>): LiveData<Result<T>> =
    liveData(Dispatchers.IO) {
        emit(Result.loading<T>())
        val source = databaseQuery.invoke().map { Result.success(it) }
        emitSource(source)

        val result = networkCall.invoke()
        if (result.status == Result.Status.ERROR) {
            emit(Result.error<T>(result.message!!))
            emitSource(source)
        }
    }

推荐答案

只有在完成新的网络请求后,才会调用存储库中的refreshShows().livedata的想法是在重新创建其片段/活动时提供最新的结果,因此,当屏幕旋转或您恢复活动时,它不会触发另一个请求,因为livedata已经具有最新的结果并且您没有与之建立状态连接您的网络数据库/服务器(如果您正在查看来自Room的数据,它将收到最新的更改).

Your refreshShows() in your repository is only get called when a new network request is done. The idea of your livedata is to provide the latest result when its fragment/activity is recreated, so when your screen rotates or you resume an activity it doesnt triggers another request as the livedata already have the latest result and you dont have a stateful connection with your network database/server (if you were observing data from Room it would receive the latest change if any).

我发现修复"此问题的最简单方法是使您的视图模型 val显示很有趣,就像这样:

The simpliest way I find to "fix" this, is to actually have your viewmodel val shows to be a fun, like this:

class MainViewModel(
    repository: ShowRepository
) : ViewModel() {

    private val _shows = repository.shows()
    val shows: LiveData<Result<List<Show>>>
        get() = _shows
}

但是使用这种方法,每次屏幕旋转时都会进行一次新的网络调用,从而调用您的 refreshShows()

However using like this, everytime the screen rotates a new network call will be made thus calling your refreshShows()

这篇关于每次调用Activity的onCreate()时都会调用Repository中的Refresh(不是在屏幕旋转中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆