Android KTX Parte do Android Jetpack.

O Android KTX é um conjunto de extensões Kotlin incluído no Android Jetpack e em outras bibliotecas do Android. As extensões do KTX oferecem Kotlin conciso e idiomático para o Jetpack, a Plataforma Android e outras APIs. Para isso, essas extensões utilizam vários recursos da linguagem Kotlin, incluindo:

  • Funções de extensão
  • Propriedades de extensão
  • Lambdas
  • Parâmetros nomeados
  • Valores padrão de parâmetro
  • Corrotinas

Por exemplo, ao trabalhar com SharedPreferences, você precisa criar um editor para poder fazer modificações nos dados de preferências. Você também precisa aplicar ou confirmar essas modificações quando terminar de editar, conforme mostrado no exemplo a seguir:

sharedPreferences
            .edit()  // create an Editor
            .putBoolean("key", value)
            .apply() // write to disk asynchronously
    

As lambdas do Kotlin são perfeitas para este caso de uso. Com elas, você pode adotar uma abordagem mais concisa passando um bloco de código para execução após a criação do editor, permitindo que o código seja executado e que a API SharedPreferences aplique as alterações atomicamente.

Veja um exemplo de uma das funções principais do Android KTX, SharedPreferences.edit, que adiciona uma função de edição a SharedPreferences. Essa função usa uma sinalização boolean opcional como primeiro argumento que indica se as mudanças serão confirmadas ou aplicadas. Ela também recebe uma ação para executar no editor SharedPreferences na forma de uma lambda.

// SharedPreferences.edit extension function signature from Android KTX - Core
    // inline fun SharedPreferences.edit(
    //         commit: Boolean = false,
    //         action: SharedPreferences.Editor.() -> Unit)

    // Commit a new value asynchronously
    sharedPreferences.edit { putBoolean("key", value) }

    // Commit a new value synchronously
    sharedPreferences.edit(commit = true) { putBoolean("key", value) }
    

O autor da chamada pode escolher entre confirmar ou aplicar as alterações. A lambda action é, por si só, uma função de extensão anônima em SharedPreferences.Editor que retorna Unit, conforme indicado pela assinatura. É por isso que, dentro do bloco, você pode executar o trabalho diretamente no SharedPreferences.Editor.

Por fim, a assinatura SharedPreferences.edit() contém a palavra-chave inline. Essa palavra-chave informa ao compilador Kotlin de que ele precisa copiar e colar (ou in-line) o bytecode compilado para a função sempre que ela for usada. Isso evita a sobrecarga de instanciar uma nova classe para cada action sempre que essa função for chamada.

Esse padrão de passagem de código usando lambdas, aplicação de padrões sensíveis que podem ser substituídos e adição desses comportamentos a APIs existentes usando funções de extensão inline é típico das melhorias fornecidas pela biblioteca Android KTX.

Usar o Android KTX no projeto

Para começar a usar o Android KTX, adicione a seguinte dependência ao arquivo build.gradle do projeto:

repositories {
        google()
    }
    

O Android KTX é organizado em módulos, e cada módulo contém um ou mais pacotes.

É necessário incluir uma dependência para cada artefato do módulo no arquivo build.gradle do app. Lembre-se de anexar o número da versão ao artefato. Por exemplo, se você usar o módulo core-ktx, a dependência totalmente formada será semelhante a esta:

dependencies {
        implementation 'androidx.core:core-ktx:1.0.1'
    }
    

Módulos

O Android KTX contém um único módulo central que fornece extensões Kotlin para APIs de framework comuns e várias extensões específicas do domínio.

Com exceção do módulo Core, todos os artefatos de módulo do KTX substituem a dependência Java subjacente no arquivo build.gradle. Por exemplo, você pode substituir uma dependência androidx.fragment:fragment por androidx.fragment:fragment-ktx. Essa sintaxe ajuda a gerenciar melhor o controle de versão e não gera outros requisitos de declaração de dependência.

Core KTX

O módulo Core KTX oferece extensões para bibliotecas comuns que fazem parte do framework do Android. Essas bibliotecas não têm dependências baseadas em Java que você precise adicionar a build.gradle.

Veja a seguir uma lista dos pacotes contidos no módulo Core KTX:

Fragment KTX

Dependência: androidx.fragment:fragment-ktx:$version. Defina ou substitua $version por um valor literal.

O módulo Fragment KTX fornece diversas extensões para simplificar a API de fragmento. Por exemplo, você pode simplificar transações de fragmentos com lambdas:

fragmentManager().commit {
       addToBackStack("...")
       setCustomAnimations(
               R.anim.enter_anim,
               R.anim.exit_anim)
       add(fragment, "...")
    }
    

Você também pode vincular um ViewModel em uma linha usando as delegações de propriedade viewModels e activityViewModels:

// Get a reference to the ViewModel scoped to this Fragment
    val viewModel by viewModels<MyViewModel>()

    // Get a reference to the ViewModel scoped to its Activity
    val viewModel by activityViewModels<MyViewModel>()
    

Palette KTX

Dependência: androidx.palette:palette-ktx:$version. Defina ou substitua $version por um valor literal.

O módulo Palette KTX oferece compatibilidade com Kotlin idiomático para trabalhar com paletas de cores.

Por exemplo, ao trabalhar com uma instância Palette, você pode recuperar a amostra selected para um determinado target usando o operador get ([ ]):

val palette = Palette.from(bitmap).generate()
    val swatch = palette[target]
    

SQLite KTX

Dependência: androidx.sqlite:sqlite-ktx:$version. Defina ou substitua $version por um valor literal.

As extensões SQLite unem o código relacionado a SQL em transações, eliminando uma grande quantidade de código de texto clichê, conforme mostrado no exemplo a seguir:

db.transaction {
        // insert data
    }
    

Collection KTX

Dependência: androidx.collection:collection-ktx:$version. Defina ou substitua $version por um valor literal.

As extensões de coleção contêm funções de utilitário para trabalhar com bibliotecas de coleções com uso eficiente da memória do Android, incluindo ArrayMap, LongParseArray, LruCache e outras.

As extensões de coleção aproveitam a sobrecarga de operadores do Kotlin para simplificar algumas coisas, como a concatenação de coleções, como mostrado no exemplo a seguir:

// Combine 2 ArraySets into 1.
    val combinedArraySet = arraySetOf(1, 2, 3) + arraySetOf(4, 5, 6)

    // Combine with numbers to create a new sets.
    val newArraySet = combinedArraySet + 7 + 8
    

ViewModel KTX

Dependência: androidx.lifecycle:lifecycle-viewmodel-ktx:$version. Defina ou substitua $version para refletir a versão mais recente do módulo.

A biblioteca ViewModel KTX fornece uma função viewModelScope() que facilita iniciar corrotinas no ViewModel. O CoroutineScope está vinculado ao Dispatchers.Main e será automaticamente cancelado quando o ViewModel for liberado (link em inglês). Você pode usar viewModelScope() em vez de criar um novo escopo para cada ViewModel.

Como exemplo, a seguinte função viewModelScope() inicia uma corrotina que faz uma solicitação de rede em uma linha de execução em segundo plano. A biblioteca processa toda a configuração e a limpeza do escopo correspondente:

class MainViewModel : ViewModel() {
        // Make a network request without blocking the UI thread
        private fun makeNetworkRequest() {
            // launch a coroutine in viewModelScope
            viewModelScope.launch  {
                remoteApi.slowFetch()
                ...
            }
        }

        // No need to override onCleared()
    }
    

Reactive Streams KTX

Dependência: androidx.lifecycle:lifecycle-reactivestreams-ktx:$version. Defina ou substitua $version por um valor literal.

O módulo Reactive Streams KTX permite criar um stream LiveData observável em um editor ReactiveStreams.

Como exemplo, considere um banco de dados com uma pequena lista de usuários. No app, você carrega o banco de dados na memória e, em seguida, exibe os dados do usuário na IU. Para conseguir isso, é possível usar RxJava. O componente Room do Jetpack pode recuperar a lista de usuários como um Flowable. Nesse cenário, você também precisa gerenciar a assinatura do editor de Rx ao longo da vida útil do seu fragmento ou atividade.

Com LiveDataReactiveStreams, no entanto, você pode se beneficiar do RxJava e do amplo conjunto de operadores e recursos de agendamento de tarefa, além de trabalhar com a simplicidade de LiveData. Como exemplo, o snippet a seguir cria um stream observável a partir de um editor Flowable do RxJava:

val fun getUsersLiveData() : LiveData<List<User>> {
        val users: Flowable<List<User>> = dao.findUsers()
        return LiveDataReactiveStreams.fromPublisher(users)
    }
    

Dependências:

  • androidx.navigation:navigation-runtime-ktx:$version
  • androidx.navigation:navigation-fragment-ktx:$version
  • androidx.navigation:navigation-ui-ktx:$version

Defina ou substitua $version por um valor literal.

Cada componente da biblioteca Navigation tem a própria versão KTX, que adapta a API para ser mais sucinta e idiomática para o Kotlin.

Use as funções de extensão e a delegação de propriedade para acessar os argumentos de destinos e navegar para eles, conforme mostrado no exemplo a seguir:

class MyDestination : Fragment() {

        // Type-safe arguments are accessed from the bundle.
        val args by navArgs<MyDestinationArgs>()

        ...
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            view.findViewById<Button>(R.id.next)
                .setOnClickListener {
                    // Fragment extension added to retrieve a NavController from
                    // any destination.
                    findNavController().navigate(R.id.action_to_next_destination)
                }
         }
         ...

    }
    

WorkManager KTX

Dependência: androidx.work:work-runtime-ktx:$version. Defina ou substitua $version por um valor literal.

O WorkManager KTX adiciona compatibilidade com corrotinas Kotlin adicionando funções de extensão a Operations e ListenableFutures para suspender a corrotina atual, conforme mostrado no exemplo a seguir:

// Inside of a coroutine...

    // Run async operation and suspend until completed.
    WorkManager.getInstance()
            .beginWith(longWorkRequest)
            .enqueue().await()

    // Resume after work completes...
    

Play Core KTX

Dependência: com.google.android.play:core-ktx:$version. Defina ou substitua $version por um valor literal.

O Play Core KTX adiciona compatibilidade com corrotinas Kotlin para solicitações únicas e fluxo para monitoramento de atualizações de status adicionando funções de extensão a SplitInstallManager e AppUpdateManager na biblioteca Play Core.

// Inside of a coroutine...

    // Request in-app update status updates.
    manager.requestUpdateFlow().collect { updateResult ->
        when (updateResult) {
            is AppUpdateResult.Available -> { TODO() }
            is AppUpdateResult.InProgress -> { TODO() }
            is AppUpdateResult.Downloaded -> { TODO() }
            AppUpdateResult.NotAvailable -> { TODO() }
        }
    }
    

Mais informações

Para saber mais sobre o Android KTX, veja o vídeo DevBytes (em inglês).

Para informar um problema ou sugerir um recurso, use o rastreador de problemas do Android KTX (link em inglês).