android kotlin CoroutineScope запустить еще раз, когда один полностью завершен - PullRequest
0 голосов
/ 24 октября 2019

У меня есть фрагмент, который имеет две функции запуска Coroutine: одна выбирает данные из сети / базы данных

, другая - чтобы проверить, пуста ли комната, и всплывающее окно для всплывающего окна для пользователя.

functions

//this function gets the data
private fun initUI() = launch {

    val data = viewModel.data.await()
    data.observe(this@fragment, Observer {
        if (it == null){
            Log.d(TAG, "initui observer is null")
            return@Observer
        }
            adapter = StoreAdapter(it, activity.baseContext)
            recyclerView.adapter = adapter
            activity.progressDisplay()
    })
    checkData().join()
}

//this function is designed to go after initUI()
private fun checkData() = launch {
    delay(3000L) //temp solution
    val check = viewModel.check.await()
    Log.d(TAG, "$check")
    if(check == 0L){
        activity.showPopup(getString(R.string.error_text), getString(R.string.data_error), retry = true)
    }
}

, если я просто проверяю dataData (). Join (), я получаю всплывающее окно, если в БД нет данных для начала, а затем работает нормально. поэтому я добавил 3-секундную задержку, однако мне не нравится этот способ, но я не уверен, есть ли другой способ?

@ edit

модели представлений простоделает отложенный задержанный, который вызывает мой репозиторий

репо init

init {
    source.downloadedData.observeForever { data->
        saveData(data)
    }
}

viewmodel.data код репо

override suspend fun getData(): LiveData<List<item>> {
    return withContext(Dispatchers.IO) {
        initJsonData()
        return@withContext myDao.getAll()
    }
}

initJsonData является датой проверкифункция, которая, если true возвращает данные из сети.

как только мы создаем init репо, мы наблюдаем данные из сети навсегда и сохраняем их в комнате дБ по мере необходимости.

просмотр кода проверки модели следует той же логике, что и получение данных в некоторой степени, но я просто делаю выборку из таблицы комнат и возвращаю результаты.

  override suspend fun checkData(): Long {
    return withContext(Dispatchers.IO) {
        Log.i(TAG, "checkData")
        isDataEmpty()
    }
}

1 Ответ

0 голосов
/ 25 октября 2019

У вас есть Observer, который постоянно наблюдает за загруженными данными, и когда он наблюдает за данными, он продолжает сохранять их в вашей БД. Но помните, что это не гарантирует, что код внутри этого наблюдателя (то есть saveData(data)) будет вызываться сразу после кода, который выбирает данные, поэтому давайте разберем его следующим образом:

  1. Когда вы вызываете метод initUI(), первая строка кода извлекает данные и ждет, пока данные будут только выбраны, и не ожидает его сохранения .

  2. После этого ваши checkData() и saveData(data) будут мчаться, чтобы выполнять свою логику одновременно. И, к сожалению, прежде чем saveData() сохранит что-либо внутри БД, checkData() вернет вам ошибку.

Одним из решений является saveData() после того, как вы его загрузили и перед вызовом checkData().join()в той же сопрограмме, как это:

private fun initUI() = launch {
    val data = viewModel.data.await()

    //Some other codes...

    saveData(data.value) //If it's an asynchronous function, await for it.


    checkData().join()    
}

Обратите внимание, что если saveData(data) является асинхронным, вы должны await для него.

...