Я новичок в анко и сопрограммах, так что извините, если я прошу что-то тривиальное :)
Итак, я пытаюсь сделать так, чтобы пользователь нажал кнопку, а затем я хочу загрузить JSON из Интернета, сохранить его локально и проанализировать его. Поскольку обе операции могут занять значительное время, я решил использовать анко-сопрограммы.
Итак, первый вопрос:
1. Могу ли я использовать вложенные вызовы doAsync, вызывая второй doAsync в UIThread первого? Я попробовал, и, похоже, он работает, но мне кажется, что это неправильно, поэтому я пытался найти более элегантный способ.
Пример:
doAsync {
downloadFileFromUrl(fileUrl)
uiThread {
doAsync {
IOUtils.parseFile(context!!)
val database = AppDatabase.getInstance(context!!)
val results = database.resultsDao().all
uiThread {
//show Results
}
}
}
}
2. В поисках решения своей проблемы я обнаружил doAsyncResult. Если 1 это неверно, правильный ли это подход? Я уже пробовал использовать его, но с логическим значением получаю ошибки. Увидеть ниже:
private fun downloadFileFromUrl(fileUrl: String): Boolean {
try{
//Download file. No doAsync calls here.
//The procedure just returns true if successful or false in case of any errors
return true
} catch (e: Exception) {
Log.e("Error: ", e.message)
return false
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
parseButton.setOnClickListener {
try {
val downloadFileResult: (AnkoAsyncContext<Boolean>.() -> Boolean) = {
::downloadFileFromUrl.invoke(fileUrl)
}
val downloadFileResultFutureValue: Future<Boolean> = doAsyncResult(null, downloadFileResult)
//Continue processing if downloadFileResultFutureValue is true
} catch (e: IOException) {
e.printStackTrace()
}
}
}
Эта линия
val downloadFileResultFutureValue: Future<Boolean> = doAsyncResult(null, downloadFileResult)
не компилируется со следующей ошибкой, которую я не понимаю, как исправить:
Type inference failed: Cannot infer type parameter T in
fun <T, R> T.doAsyncResult
(
exceptionHandler: ((Throwable) → Unit)? = ...,
task: AnkoAsyncContext<T>.() → R
)
: Future<R>
None of the following substitutions
receiver: Boolean
arguments:
(
((Throwable) → Unit)?,
AnkoAsyncContext<Boolean>.() → Boolean
)
receiver: BlankFragment
arguments:
(
((Throwable) → Unit)?,
AnkoAsyncContext<BlankFragment>.() → Boolean
)
can be applied to
receiver: BlankFragment
arguments:
(
Nothing?,
AnkoAsyncContext<Boolean>.() → Boolean
)
заранее спасибо
Делая это:
doAsync {
// 1. Something
uiThread {
// 2. Nothing
doAsync {
В самом деле, это не имеет особого смысла, если (2) не является ничем, и вы просто пропустили какой-то код. Если вы этого не сделали, вы можете просто остаться с этой версией:
doAsync {
downloadFileFromUrl(fileUrl)
IOUtils.parseFile(context!!)
val database = AppDatabase.getInstance(context!!)
val results = database.resultsDao().all
uiThread {
//show Results
}
}
Поскольку parseFile() в любом случае зависит от downloadFileFromUrl(), и все работает в сопрограмме, вы не станете более параллельным, добавив это взад и вперед.
Хорошо, если я правильно понял, что вы имеете в виду, все, что находится в doAsync, выполняется последовательно. Итак, сначала файл будет загружен. После загрузки файл будет проанализирован, и, наконец, будет вызвана база данных для отображения на экране. Что ж, теперь это имеет гораздо больше смысла :). Спасибо