Предисловие
Kotlin Coroutines - это новый асинхронный API, запущенный Kotlin. Не лучшее решение для всех проблем, но, надеюсь, во многих случаях это сделает ситуацию немного проще. Здесь я просто покажу конкретный план использования этой библиотеки в Android. Я не скажу многое ниже, давайте посмотрим на подробное введение вместе.
Представление коратиков
// Добавить следующий код в узле Android в файле build.gradle приложения Kotlin {Experimental {coroutines 'enable'}} // Добавить следующие две строки в реализацию зависимости "org.jetbrains.kotlinx: kotlinx-coroutines-core: 0.20" реализация "org.jetbrains.kotlinx: kotlinx-cor-corouns-corounx-corounx-corine-corine-corine-corine-corines-corinx-10Первый пример Coroutines
Обычно мы загружаем изображение в ImageView, а задача асинхронной загрузки заключается в следующем:
FUN LOADBITMAPFROMMEDIASTORE (ImageID: int, ImagesBaseuri: uri): растровый {val uri = uri.withappendedPath (imageSbaseuri, imageId.toString ()) return mediastore.images.media.getbitmap (contentresolver, uri)}Этот метод должен быть выполнен в фоновом потоке, потому что он принадлежит операции ввода -вывода, что означает, что у нас есть много решений для запуска фоновой задачи, и как только метод возвращает растровое изображение, нам нужно немедленно отобразить его в ImageView.
ImageView.setImageBitmap (растровый карта)
Эта строка кода должна быть выполнена в основном потоке, в противном случае она будет сбой.
Если вышеупомянутые три строки кода записаны вместе, программа будет застряла или разбита, что зависит от разумного выбора потоков. Далее, давайте посмотрим, как CORUTINES с использованием Kotlin решает эту проблему:
val job = запуск (fourene) {val uri = uri.withappendedPath (imageSbaseuri, imageId.toString ()) val bitmap = mediastore.images.media.getbitmap (contentresolver, ui) {imageview.setimagebitmap (bitmap)}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}.Самая важная вещь здесь - запуск () и параметры и пользовательский интерфейс. Запуск () означает создание и запуск коратики. Фоновый параметр CoroutIneContext используется для обеспечения выполнения в фоновом потоке, чтобы гарантировать, что приложение не будет застряло или не удалось. Вы можете объявить CoroutineContext, как показано ниже.
Внутренний val founal = newfixedthreadpoolcontext (2, "bg")
Это создает новый контекст и использует два обычных потока при выполнении своих задач.
Далее, запуск (пользовательский интерфейс), который запустит еще одну корутину, которая будет выполнена на Android
Главная нить.
Отмену
Следующая задача - справиться с вещами, связанными с циклом декларации деятельности. Когда вы загружаете задачу и оставляете действие до завершения выполнения, это приведет к сбою при вызове imageView.setImageBitmap(bitmap) , поэтому нам нужно отменить задачу перед тем, как покинуть деятельность. Здесь мы используем возвращаемое значение метода запуска (). Когда действие вызывает метод Onstop, нам нужно использовать задание, чтобы отменить задачу.
job.cancel ()
Это все равно, что вызовет утилизацию, когда вы используете rxjava и вызов функции отмены при использовании Asynctask.
LifeCycleobserver
Компоненты архитектуры Android предоставляют разработчикам Android много мощных библиотек, одним из которых является API жизненного цикла. Это дает нам простой способ выслушать жизненный цикл деятельности и фрагментов в режиме реального времени. Давайте определим код для использования с Coroutines.
class CoroutineLifecycleListener(val deferred: Deferred<*>) : LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun cancelCoroutine() { if (!deferred.isCancelled) { deferred.cancel() } }}Мы создаем функцию расширения LifeCycleowner:
Веселье <t> lifeCycleOwner.load (Loader: () -> t): deferred <t> {val deferred = async (context = founale, start = coroutinestart.lazy) {Loader ()} LifeCycle.Addobserver (coroutinelifecyclistener (deferred)) referred}}}}}}}}}}}}} В этом методе слишком много новых вещей, и я объясню их один за другим:
Теперь мы можем вызвать load() в действие или фрагменте, и получить доступ к членам жизненного цикла из этой функции и добавить нашу Coroutinelifecyclelistener в качестве наблюдателя.
Метод загрузки требует загрузчика в качестве параметра, возвращающего общий тип T. В методе нагрузки мы называем другую функцию Coroutine Creator Async (), которая будет использовать фоновый контекст Coroutine для выполнения задач в фоновом потоке. Обратите внимание, что этот метод имеет еще один параметр start = coroutinestart.lazy, что означает, что Coroutine не будет выполнена немедленно, пока он не будет вызван.
Затем Coroutine вернет Defered<T> для вызывающего абонента, который аналогичен нашей предыдущей работе, но также может содержать значение задержки, например, JavaScript Promise или Future <T> в обычном API Java, и, что еще лучше, у него есть метод ожидания.
Затем мы определяем другую функцию расширения then() , на этот раз мы определяем ее выше Deferen<T> , которая является типом, возвращаемым нашим методом нагрузки выше. Он также требует лямбды в качестве параметра, названного блока, который принимает один объект типа T в качестве параметра.
Infix Fun <t> deferred <t> .Then (block: (t) -> Unit): job {return warner (context = ui) {block ([email protected] ())}} Эта функция создаст другую Coroutine, используя функцию launch() , которая будет работать на основном потоке на этот раз. Lambda (названный блок), переданная в эту кораку, принимает значение завершенного отложенного объекта в качестве параметра. Мы называем await() , чтобы приостановить выполнение этой коратики до тех пор, пока отложенный объект не вернет значение.
Вот где Coroutine становится таким впечатляющим. Призыв await() выполняется в основном потоке, но не блокирует дальнейшее выполнение этого потока. Он просто приостановит выполнение функции, пока не будет готова, когда она возобновится, и передаст отложенное значение для лямбды. Когда коратика приостановлен, главный поток может продолжать выполнять другие вещи. Функция ожидания является основной концепцией в Coroutine, что создает все это так волшебно.
Наблюдатель Lifecycle, добавленный в функцию load() отменит первую Coroutine после вызова onDestroy() на нашу деятельность. Это также приведет к аннулированию второго Coroutine, предотвращающего block() .
Kotlin Coroutine DSL
Теперь, когда у нас есть две функции расширения и класс, который обрабатывает отмену Coroutine, давайте посмотрим, как его использовать:
Load {LoatBitMapFrommediastore (imageId, imageSbaseuri)} then {imageView.setImageBitmap (it)} В приведенном выше коде мы передаем метод лямбда в функцию загрузки, которая вызывает метод LoadbitMapFrommediastore, который должен быть выполнен в фоновом потоке, пока метод не вернет растровый карту, и возвращаемое значение метода нагрузки Deferred<Bitmap> .
В качестве функции расширения метод then() использует инфиксное объявление. Хотя метод нагрузки возвращает Deferred<Bitmap> , он будет передаваться в тогдашний метод обратного значения растрового изображения, поэтому мы можем напрямую вызову imageView.setImageBitmap(it) в следующем методе.
Приведенный выше код может использоваться для любых асинхронных вызовов, которые должны происходить в фоновом потоке, и где возвращаемое значение должно быть возвращено в основной поток, как в приведенном выше примере. Он не делает несколько вызовов, как и Rxjava, но его легче читать и может охватить множество наиболее распространенных случаев. Теперь вы можете сделать что -то вроде этого безопасно, не беспокоясь о том, чтобы вызвать утечки контекста или обработку потоков в каждом вызове;
загрузка {restapi.fetchData (Query)} then {adapter.display (it)}Затем () и погрузочные () методы являются лишь вершиной айсберга этой новой библиотеки, но я надеюсь, что что-то подобное появится в будущих библиотеках Android на основе Kotlin, как только версия Coroutine достигнет стабильной версии. Перед этим вы можете использовать или изменить приведенный выше код или проверить Coroutines Anko. Я также выпустил более полную версию на GitHub. (https://github.com/erikhellman/kotlinasyncwithcoroutines (локальная загрузка)).
Суммировать
Вышеуказанное - все содержание этой статьи. Я надеюсь, что содержание этой статьи имеет определенную справочную ценность для каждого обучения или работы. Если у вас есть какие -либо вопросы, вы можете оставить сообщение для общения. Спасибо за поддержку Wulin.com.