Shared ViewModel para ajudar na comunicação entre fragmentos e atividade pai

Enquanto o componente Navegação do JetPack parece bastante promissor, cheguei a um lugar em que não conseguia encontrar uma maneira de implementar o que queria.

Vamos dar uma olhada em uma tela de exemplo de aplicativo:

O aplicativo tem uma atividade principal, uma barra de ferramentas superior, uma barra de ferramentas inferior com fab anexado. Existem 2 desafios que estou enfrentando e quero fazê-los da maneira certa.

1. Preciso implementar transações de fragmento para permitir a substituição do fragmento na tela, com base na interação do usuário. Existem três maneiras de pensar e implementar isso:

o retorno de chamada. Tendo uma interfaceonFragmentAction retorno de chamada em fragmento e ter atividade implementá-lo. Então, basicamente, quando o usuário pressiona um botãoFragmentA eu posso ligaronFragmentAction com parâmetros, para que a atividade seja acionada e inicie, por exemplo, uma transação para substituí-la porFragmentBimplementoNavigation componente do JetPack. Embora eu tenha tentado e pareça bem direto, tive um problema ao não conseguir recuperar o fragmento atual.Use um compartilhadoViewModel entre fragmento e atividade, atualize-o e observe-o na atividade. Isso seria uma "substituição" dos retornos de chamada

2. Desde oFAB está na atividade pai, quando pressionado, preciso poder interagir com o fragmento visível atual e executar uma ação. Por exemplo, adicione um novo item em uma reciclagem dentro do fragmento. Então, basicamente, uma maneira de se comunicar entre a atividade e o fragmento Existem duas maneiras de pensar em como fazer isso

Se não estiver usandoNavigation então eu posso usarfindFragmentById e recupere o fragmento atual e execute um método público para acionar a ação.Usando um 'ViewMode' compartilhado entre fragmento e atividade, atualize-o da atividade e observe-o no fragmento.

Portanto, como você pode ver, a maneira recomendada de fazer a navegação seria usar o novo componente da arquitetura 'Navigation', no entanto, no momento, falta uma maneira de recuperar a instância atual do fragmento para que eu não saiba como me comunicar. a atividade e fragmento. Isso pode ser alcançado comshared ViewModel mas aqui tenho uma peça que falta: entendo que a comunicação entre fragmentos pode ser feita com um ViewModel compartilhado. Eu acho que isso faz sentido quando os fragmentos têm algo em comum para isso, como um cenário Mestre / Detalhe e compartilhar o mesmo modelo de exibição é muito útil.

Mas, então, falando entre atividade eTUDO fragmentos, como poderiaViewModel ser usado? Cada fragmento precisa de seu próprio ViewModel complexo. Poderia ser umGeneralViewModel que é instanciado na atividade e em todos os fragmentos, junto com o modelo de exibição de fragmento regular, portanto, tem 2 modelos de exibição em cada fragmento.

Ser capaz de falar entre fragmentos e atividade com um viewmodel tornará desnecessário o achado de fragmento ativo, pois o viewmodel fornecerá o mecanismo necessário e também permitirá o usoNavigation componente.

Qualquer informação é recebida com prazer.

Depois edite. Aqui está um exemplo de código com base no comentário abaixo. Esta é uma solução para minha pergunta? Isso pode lidar com as alterações entre os fragmentos e a atividade dos pais e está no lado recomendado.

 private GlobalViewModel ():ViewModel(){

      var eventFromActivity:MutableLiveData<Event>
      var eventFromFragment:MutableLiveData<Event>


      fun setEventFromActivity(event:Event){
          eventFromActivity.value = event
      }

      fun setEventFromFragment(event:Event){
          eventFromFragment.value = event
      }

 } 

Então na minha atividade

class HomeActivity: AppCompatActivity(){

   onCreate{
       viewModel = ViewModelProviders.of(this, factory)
                .get(GlobalViewModel::class.java)

        viewModel.eventsFromFragment.observe(){
           //based on the Event values, could update toolbar title, could start
           // new fragment, could show a dialog or snackbar
        ....
        }   

     //when need to update the fragment do 
     viewModel.setEventFromActivity(event)
   }
}

Então em todos os fragmentos tem algo parecido com isto

class FragmentA:Fragment(){

  onViewCreated(){

       viewModel = ViewModelProviders.of(this, factory)
                .get(GlobalViewModel::class.java)

        viewModel.eventsFromActivity.observe(){
           // based on Event value, trigger a fun from the fragment 
        ....
        }

        viewModelFragment = ViewModelProviders.of(this, factory)
            .get(FragmentAViewModel::class.java)

        viewModelFragment.some.observe(){
        ....
        }   

  //when need to update the activity do 
     viewModel.setEventFromFragment(event)      
  }

}

questionAnswers(0)

yourAnswerToTheQuestion