Prefácio
Kotlin Coroutines é uma nova API assíncrona lançada por Kotlin. Não é a melhor solução para todos os problemas, mas espero que, em muitos casos, facilite as coisas. Aqui vou simplesmente mostrar o plano de uso específico desta biblioteca no Android. Não vou dizer muito abaixo, vamos dar uma olhada na introdução detalhada juntos.
Apresentando Coroutines
// Adicione o seguinte código no nó Android no arquivo Build.gradle do aplicativo Kotlin {Experimental {Coroutines 'Enable'}} // Adicione as duas linhas a seguir à implementação da dependência "Org.JetBrains.JetBrains.KOTlinx-coro-core: 0,20" "Org.jetlinx.kotlinx-core: 0.20" "Org.jetlinx.kotlinx.kotlinx-core: 0.20"O primeiro exemplo de coroutinas
Normalmente, carregamos uma imagem no ImageView, e a tarefa de carregamento assíncrona é a seguinte:
FUN LOUTBITMAPFROMEDIASTORE (ImageId: int, ImagesBaseuri: URI): Bitmap {val uri = uri.withappendedPath (ImagesBaseuri, imageId.toString ()) Return MediaStore.images.media.getBitmap (contentResolver, uri)}Esse método deve ser executado no encadeamento de segundo plano, pois pertence a uma operação de IO, o que significa que temos muitas soluções para iniciar a tarefa de segundo plano e, uma vez que o método retorne um bitmap, precisamos exibi -lo no ImageView imediatamente.
ImageView.setImageBitmap (bitmap)
Essa linha de código deve ser executada no encadeamento principal, caso contrário, ele falhará.
Se as três linhas de código acima forem escritas juntas, o programa ficará preso ou travado, o que depende da seleção razoável de threads. Em seguida, vamos dar uma olhada em como os coroutines usando Kotlin resolvem esse problema:
Val Job = Launch (Background) {val uri = uri.withapendedPath (Imagesbaseuri, imageid.toString ()) val bitmap = mediastore.images.media.getMap (contentResolver, lançamento (UI) {imageview.setImageBitmap (bitmap)}}}}O mais importante aqui é o fundo do lançamento () e dos parâmetros e interface do usuário. Launcy () significa criar e iniciar uma coroutina. O parâmetro de segundo plano coroutineContext é usado para garantir a execução no encadeamento de segundo plano, para garantir que o aplicativo não fique preso ou travado. Você pode declarar um CoroutineContext, como mostrado abaixo.
Antecedentes internos do Val = newFixedThreadpoolContext (2, "BG")
Isso cria um novo contexto e usa dois threads regulares ao executar suas tarefas.
Em seguida, o lançamento (interface do usuário), que desencadeará outra coroutina, que será executada no Android
Tópico principal.
Cancelável
O próximo desafio é lidar com as coisas relacionadas ao ciclo da declaração de atividade. Quando você carrega uma tarefa e deixa a atividade antes de terminar de executar, ela causará falha ao chamar imageView.setImageBitmap(bitmap) , por isso precisamos cancelar a tarefa antes de deixar a atividade. Aqui, usamos o valor de retorno do método de lançamento (). Quando a atividade chama o método Onstop, precisamos usar o trabalho para cancelar a tarefa.
Job.Cancel ()
É como ligar para o Dispone quando você usa o RXJava e o Calling Cancel Função quando você usa asyncTask.
LifeCycleObServer
Os componentes da arquitetura Android fornecem aos desenvolvedores do Android muitas bibliotecas poderosas, uma das quais é a API do ciclo de vida. Ele nos fornece uma maneira fácil de ouvir o ciclo de vida de atividades e fragmentos em tempo real. Vamos definir o código a ser usado com as coroutinas.
classe CoroutinelifeCycleListener (Val adiada: adiada <*>): LIFECYCYLOBSERVER {@onLifeCycleEvent (lifecycle.event.on_destroy) cancelcoroutine () {if (!Criamos uma função de extensão do proprietário de vida:
diversão <t> LifeCyclecowner.load (carregador: () -> t): adiado <t> {val adferred = assync (context = background, start = coroutinestart.lazy) {loader ()} lifecycle.addobserver (corooutinelifecycleListener (diferred)) deferido}}} Há muitas coisas novas nesse método, e eu as explicarei uma a uma:
Agora, podemos chamar load() em uma atividade ou fragmento e acessar os membros do ciclo de vida dessa função e adicionar nosso CoroutinelifeCycleListener como observador.
O método de carga requer um carregador como um parâmetro, retornando um tipo geral T. No método de carga, chamamos outra função de criador de coroutine async (), que usará o contexto da coroagem de fundo para executar tarefas no encadeamento de segundo plano. Observe que este método possui outro parâmetro start = coroutinestart.lazy, o que significa que a coroutina não será executada imediatamente, até que seja chamada.
A Coroutine retornará um objeto Defered<T> para o chamador, que é semelhante ao nosso trabalho anterior, mas também pode carregar um valor de atraso, como JavaScript Promise ou Future <T> em uma API Java regular e, melhor ainda, tem um método aguardando.
Em seguida, definimos outra função de extensão then() , desta vez a definimos acima Deferen<T> , que é o tipo retornado pelo nosso método de carga acima. Também é necessário um parâmetro Lambda, chamado Block, que leva um único objeto do tipo T como seu parâmetro.
infix diversão <t> diferida <T> .Then (Block: (t) -> unidade): Job {Return Launch (Context = UI) {Block ([email protected] ())}} Esta função criará outra coroutina usando launch() , que será executada no thread principal desta vez. O lambda (bloco nomeado) passou para esta coroutina assume o valor do objeto diferido preenchido como seu parâmetro. Ligamos await() para suspender a execução desta coroutina até que o objeto diferido retorne um valor.
Aqui é onde a Coroutine se torna tão impressionante. A chamada para await() é feita no encadeamento principal, mas não bloqueia a execução adicional desse thread. Ele simplesmente pausa a execução da função até que esteja pronta, quando retomar e passar o valor atrasado para o Lambda. Quando a coroutina é suspensa, o encadeamento principal pode continuar realizando outras coisas. A função aguardada é um conceito central na coroutina, o que cria a coisa toda tão mágica.
O observador do ciclo de vida adicionado na função load() cancelará a primeira coroutina depois de ligar para onDestroy() em nossa atividade. Isso também fará com que a segunda coroutina seja cancelada, impedindo que block() seja chamado.
Kotlin Coroutine DSL
Agora que temos duas funções de extensão e uma classe que lida com o cancelamento da coroutina, vamos ver como usá -la:
Load {loadBitMapFromDiAstore (ImageId, ImagesBaseuri)} então {ImageView.SetImageBitMap (It)} No código acima, passamos o método Lambda para a função de carga, que chama o método loadBitMapFromDiastore, que deve ser executado no encadeamento de segundo plano até que o método retorne um bitmap e o valor de retorno do método de carga seja Deferred<Bitmap> .
Como uma função de extensão, then() usa a declaração de infix. Embora o método de carga retorne Deferred<Bitmap> , ele será passado para o método então um valor de retorno de bitmap, para que possamos chamar diretamente imageView.setImageBitmap(it) no método então.
O código acima pode ser usado para quaisquer chamadas assíncronas que precisam ocorrer no encadeamento em segundo plano e onde o valor de retorno deve ser retornado ao encadeamento principal, como no exemplo acima. Não faz várias chamadas como o RXJava, mas é mais fácil de ler e pode cobrir muitos dos casos mais comuns. Agora você pode fazer algo assim com segurança, sem se preocupar em causar vazamentos de contexto ou processando threads em todas as chamadas;
carregar {RESTAPI.FetchData (Query)} Então {Adapter.Display (It)}Então () e os métodos de carregamento () são apenas a ponta do iceberg desta nova biblioteca, mas espero que algo semelhante apareça nas futuras bibliotecas Android baseadas em Kotlin, quando a versão coroutine atingir uma versão estável. Antes disso, você pode usar ou modificar o código acima ou conferir as Coroutinas ANKO. Também lançei uma versão mais completa no Github. (https://github.com/erikhellman/kotlinaasyncwithcoroutines (download local)).
Resumir
O acima é o conteúdo inteiro deste artigo. Espero que o conteúdo deste artigo tenha certo valor de referência para o estudo ou trabalho de todos. Se você tiver alguma dúvida, pode deixar uma mensagem para se comunicar. Obrigado pelo seu apoio ao wulin.com.