LiveData vs Kotlin Flow

10

No último Google I / O, Jose Alcerreca e Yigit Boyar nos disseram que não devemos mais usar o LiveData para buscar dados. Agora devemos usar as funções de suspensão para buscas de uma só vez e usar o Flow de Kotlin para criar um fluxo de dados. Concordo que as corotinas são ótimas para obter buscas de uma só vez ou outras operações CRUD, como inserir etc. etc. Mas nos casos em que preciso de um fluxo de dados, não entendo quais vantagens o Flow me oferece. Parece-me que o LiveData está fazendo o mesmo.

Exemplo com fluxo:

ViewModel

val items = repository.fetchItems().asLiveData()

Repositório

fun fetchItems() = itemDao.getItems()

Dao

@Query("SELECT * FROM item")
fun getItems(): Flow<List<Item>>

Exemplo com LiveData:

ViewModel

val items = repository.fetchItems()

Repositório

fun fetchItems() = itemDao.getItems()

Dao

@Query("SELECT * FROM item")
fun getItems(): LiveData<List<Item>>

Eu também gostaria de ver alguns exemplos de projetos usando corotinas e Flow para trabalhar com o Room ou Retrofit. Encontrei apenas uma amostra de ToDo do Google em que as corotinas são usadas para obter uma captura e, em seguida, refazer manualmente os dados sobre alterações.

Dmitry Simakov
fonte

Respostas:

3

Flowé uma espécie de reactive stream(como rxjava). Há um monte de diferentes operadores como .map, buffer()(de qualquer maneira menos não. Do operador de comparação com rxJava). Portanto, uma das principais diferenças entre LiveDatae Flowé que você pode assinar o mapa computation / transformationem algum outro segmento usando

 flowOn(Dispatcher....). 

Então, por exemplo: -

 flowOf("A","B","C").map { compute(it) }.flowOn(Dispatchers.IO).collect {...} // U can change the execution thread of the computation ( by default its in the same dispatcher as collect )

Com LiveDatae map, o acima não pode ser alcançado diretamente!

Portanto, é recomendável manter o fluxo no nível do repositório e transformar os dados vivos uma ponte entre a interface do usuário e o repositório!

A principal diferença é que flowtem um monte de operadores diferentes que livedatanão tem! Mas, novamente, cabe a você como você quer construir seu projeto!

Santanu Sur
fonte
3

Como o nome sugere, você pode pensar no Flow como um fluxo contínuo de vários valores calculados de forma assíncrona. A principal diferença entre o LiveData e o Flow, do meu ponto de vista, é que um Flow emite resultados continuamente, enquanto o LiveData atualiza quando todos os dados são buscados e retorna todos os valores de uma só vez. No seu exemplo, você está buscando valores únicos, o que não é exatamente o que o Flow foi feito na minha opinião.

Não tenho um exemplo de sala, mas digamos que você esteja processando algo que leva tempo, mas deseja exibir resultados enquanto processa e armazena em buffer os próximos resultados.

private fun render(stuffToPlay: List<Any>): Flow<Sample> = flow {
     val sample = Sample()
     // computationally intensive operation on stuffToPlay
     Thread.sleep(2000)
     emit(sample)
}

Então, na sua função 'Reprodução', você pode, por exemplo, exibir os resultados em que stuffToPlay é uma lista de objetos para renderizar, como:

playbackJob = GlobalScope.launch(Dispatchers.Default) {

    render(stuffToPlay)
        .buffer(1000)   // tells the Flow how many values should be calculated in advance

        .onCompletion {
            // gets called when all stuff got played
        }
        .collect{sample ->
           // collect the next value in the buffered queue
           // e.g. display sample
        }
}

Uma característica importante do Flow é que seu código de construtor (aqui função de renderização) só é executado quando é coletado, portanto é um fluxo frio .

Você também pode consultar os documentos em Fluxo assíncrono

nulldroid
fonte