Por que não estou usando o SharedViewModel para fragmentos?

Habr, olá!

A tarefa de organizar a interação entre fragmentos é muito comum. À primeira vista, o ShareViewModel é ótimo para isso. Criamos um ViewModel com owner = nossa atividade, na qual nossos fragmentos são exibidos, e obtemos esse ViewModel dentro de cada fragmento. Porque o proprietário do ViewModel é uma atividade, os fragmentos obtêm a mesma instância do ViewModel, que permite trocar dados, chamar métodos etc. Aqui está o link da documentação .

A figura abaixo mostra o esquema de interação de 3 fragmentos.

imagem

Essa. o que fazemos: em cada fragmento, obtemos o SharedViewModel daqueles fragmentos com os quais precisamos interagir ...

E essa não é a melhor solução, na minha opinião. Porque:

  1. *VM. ViewModel View. ViewModel LiveData, View, .. ViewModel - , View.
  2. SharedViewModel — . , SharedViewModel , , . - .
  3. SharedViewModel, . , , .

O SharedViewModel pode ser usado apenas quando houver vários fragmentos completamente idênticos com os mesmos dados. Na minha prática, não havia esse cenário. Pode haver dois fragmentos idênticos, mas o estado do ViewModel de cada um é diferente, o SharedViewModel é inválido para eles.

O SharedViewModel traz muitos problemas. Você começa a ficar confuso, tudo está cheio de dependências, o código é complicado. É muito mais fácil trabalhar quando o Fragment + ViewModel é uma caixa preta.

Que solução pode ser oferecida?

Um serviço simples com o qual cada fragmento interage à sua maneira.

imagem

Este serviço deve ser passado dentro de cada ViewModel. Graças ao DI e ao escopo (Dagger, Koin, qualquer outro), isso pode ser feito de maneira fácil e simples. Se o serviço estiver no contexto de uma Atividade, crie-o no Escopo desta Atividade e passe-o para cada ViewModel.

Veja o que aconteceu: removemos todos os SharedViewModel dos fragmentos. Cada fragmento agora não sabe nada sobre os outros fragmentos. Se queremos adicionar um novo fragmento a esse esquema, precisamos apenas conectar o viewModel D ao nosso serviço e é isso. Se o fragmento responder a uma alteração em alguma propriedade do serviço - basta se inscrever. Não precisamos mais entender os modelos de vista de outras pessoas. E esse serviço será muito mais simples do que qualquer ViewModel, será mais fácil entender o serviço.

Pode parecer que não há tantos fragmentos interagindo em uma tela. No telefone - talvez. No tablet - você não pode mais dizer isso. E o FragmentContainerView ajuda a usar fragmentos em qualquer layout, o que é muito conveniente se o aplicativo tiver muitos componentes comuns com um ciclo de vida.

Bônus: como faço para criar fragmentos?


Assim: SomeFragment ()

E os parâmetros?

Com o advento do ViewModel, eu não uso parâmetros. Eu não passo nada para o fragmento via pacote (o Android Studio ainda se oferece para criar um fragmento com argumentos e criar um fragmento através do método estático), não uso o NavArgs de segurança para o componente de navegação .

Todas essas coisas tornam o fragmento condicionado. Não podemos simplesmente pegar esse fragmento e adicioná-lo ao ViewPager, por exemplo. É preciso pensar em como passar os parâmetros. Ou outro exemplo: você criou um fragmento com parâmetros, trabalha nele, os dados foram alterados, o fragmento já mostra outra coisa. Alteramos a configuração do dispositivo (invertida), o fragmento foi criado novamente com parâmetros desatualizados, enquanto o ViewModel já contém outros dados. E a atualização dos parâmetros começa, etc.

Eu removi tudo isso no ViewModel. Eu uso o mesmo serviço pelo qual passo os parâmetros. Funciona como o Safety NavArgs. ViewModel solicita parâmetros do serviço pelo tipo da classe de parâmetro. Após recuperar o parâmetro com êxito, o serviço os exclui (funciona como Push / Pop).

Isso resolve imediatamente o problema de alterar a configuração: o fragmento foi criado novamente e o ViewModel já está com os dados atuais, tudo o que é necessário é conectá-los ao View.

Também há um problema ao passar parâmetros pelo pacote - isso é um excesso da quantidade permitida. Se a quantidade de dados transferidos for superior a 500 kb., O aplicativo poderá falhar devido a uma exceção no Binder.java. Isso levou à criação de diferentes bibliotecas que transmitem parâmetros via SD, o que não é muito rápido se comparado ao uso da RAM.

Em geral, as ferramentas são legais, tudo é flexível, mas você precisa ter cuidado.

Isso é tudo, obrigado por assistir!

All Articles