Migrar a navegação do Jetpack para o Navigation Compose

A API Navigation Compose permite navegar entre elementos combináveis em uma app Compose, além de aproveitar o componente de navegação do Jetpack, infraestrutura e atributos.

Esta página descreve como migrar de uma navegação do Jetpack baseada em fragmentos para Navigation Compose, como parte da migração maior de interface baseada em visualização para o Jetpack Escrever.

Pré-requisitos de migração

Você pode migrar para o Navigation Compose depois de substituir todos os seus Fragmentos com elementos combináveis de tela correspondentes. Os elementos combináveis da tela podem conter uma combinação de conteúdo do Compose e do View, mas todos os destinos de navegação precisam ser combináveis para ativar a migração do Navigation Compose. Até lá, você deve continue usando o componente de navegação baseado em fragmentos na visualização de interoperabilidade e Base de código do Compose. Consulte a documentação de interoperabilidade de navegação para saber mais. informações imprecisas ou inadequadas.

O uso do Navigation Compose em um app somente do Compose não é um pré-requisito. Você pode continuar usando o componente de navegação baseado em fragmentos, desde que você mantenha Fragmentos para hospedar conteúdo combinável.

Etapas da migração

Se você está seguindo nossa estratégia de migração recomendada ou fazendo outra abordagem, você chegará a um ponto em que todos os destinos de navegação estarão elementos combináveis de tela, com fragmentos atuando apenas como contêineres combináveis. Neste você pode migrar para a navegação do Compose.

Caso seu app já esteja seguindo um padrão de design de UDF e nosso guia para do BigQuery, a migração para o Jetpack Compose e o Navigation Compose não deveria exigem grandes refatorações de outras camadas do app, além da camada da interface.

Para migrar para o Navigation Compose, siga estas etapas:

  1. Adicione a dependência do Navigation Compose ao app.
  2. Crie um elemento App-level combinável e adicione-o ao Activity como seu Ponto de entrada do Compose, substituindo a configuração do layout de visualização:

    class SampleActivity : ComponentActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample)
            setContent {
                SampleApp(/* ... */)
            }
        }
    }

  3. Configurar o NavController em um local em que todos os elementos combináveis que precisam para referenciá-lo, tenha acesso a ele (isso geralmente está dentro de seu App combinável). Essa abordagem segue os princípios de elevação de estado e permite usar NavController como a fonte da verdade para navegação. entre as telas combináveis e manter a backstack:

    @Composable
    fun SampleApp() {
        val navController = rememberNavController()
        // ...
    }

  4. Crie o NavHost do app dentro do elemento combinável do app e transmita o navController:

    @Composable
    fun SampleApp() {
        val navController = rememberNavController()
    
        SampleNavHost(navController = navController)
    }
    
    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = "first") {
            // ...
        }
    }

  5. Adicione os destinos composable para criar seu gráfico de navegação. Se cada tela foi migrada anteriormente para o Compose, esta etapa consiste apenas em extraímos esses elementos combináveis de tela dos fragmentos para o composable. destinos:

    class FirstFragment : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View {
            return ComposeView(requireContext()).apply {
                setContent {
                    // FirstScreen(...) EXTRACT FROM HERE
                }
            }
        }
    }
    
    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = "first") {
            composable("first") {
                FirstScreen(/* ... */) // EXTRACT TO HERE
            }
            composable("second") {
                SecondScreen(/* ... */)
            }
            // ...
        }
    }

  6. Se você seguiu as orientações sobre como arquitetar a interface do Compose: Especificamente, como ViewModels e eventos de navegação devem ser transmitidos ao elementos combináveis, a próxima etapa é mudar a forma como o ViewModel é fornecido para cada elemento combinável de tela. Muitas vezes, é possível usar a injeção e a integração do Hilt com o Compose e a navegação via hiltViewModel:

    @Composable
    fun FirstScreen(
        // viewModel: FirstViewModel = viewModel(),
        viewModel: FirstViewModel = hiltViewModel(),
        onButtonClick: () -> Unit = {},
    ) {
        // ...
    }

  7. Substitua todas as chamadas de navegação findNavController() pelo navController. e transmiti-los como eventos de navegação para cada tela combinável, em vez do que transmitir todo o navController. Essa abordagem segue a melhor práticas de exposição de eventos de funções combináveis aos autores de chamadas e mantém o navController como a única fonte da verdade.

    1. Se você já usou o plug-in Safe Args para gerar instruções e ações de navegação, substitua-o por um trajeto, um Caminho de string para o elemento combinável, exclusivo para cada destino.
    2. Para substituir o Safe Args ao transmitir dados, consulte Navegar com Argumentos de venda.
    3. Para segurança de tipos no Navigation Compose, leia a seção Safe Args. a seguir.

      @Composable
      fun SampleNavHost(
          navController: NavHostController
      ) {
          NavHost(navController = navController, startDestination = "first") {
              composable("first") {
                  FirstScreen(
                      onButtonClick = {
                          // findNavController().navigate(firstScreenToSecondScreenAction)
                          navController.navigate("second_screen_route")
                      }
                  )
              }
              composable("second") {
                  SecondScreen(
                      onIconClick = {
                          // findNavController().navigate(secondScreenToThirdScreenAction)
                          navController.navigate("third_screen_route")
                      }
                  )
              }
              // ...
          }
      }

  8. Remover todos os fragmentos, layouts XML relevantes, navegação desnecessária e outros e dependências desatualizadas de Fragment e Jetpack Navigation.

Você pode encontrar as mesmas etapas com mais detalhes relacionados à navegação do Compose na Documentação de configuração.

Casos de uso comuns

Independentemente do componente de navegação usado, os mesmos princípios de navegação são aplicáveis.

Confira alguns casos de uso comuns da migração:

Para informações mais detalhadas sobre esses casos de uso, consulte Navegar com o Compose.

Safe Args

Ao contrário do Jetpack Navigation, o Navigation Compose não oferece suporte ao uso do recurso Plug-in Args para gerar código. Em vez disso, você pode conseguir segurança de tipos com Navegue pelo Compose ao estruturar o código para torná-lo seguro de tipo em no ambiente de execução.

Recuperar dados complexos durante a navegação

O Navigation Compose é baseado em rotas de string e, ao contrário do Jetpack Navigation, não não oferece suporte à transmissão de Parcelables personalizados e Serializados como argumentos.

É altamente recomendável não transmitir objetos de dados complexos durante a navegação. Em vez disso, transmita o mínimo de informações necessárias, como um identificador exclusivo ou outra forma de ID, como argumentos ao realizar ações de navegação. Você deve armazenar objetos complexos como dados em uma única fonte de verdade, como a fonte de dados camada. Para mais informações, consulte Como recuperar dados complexos ao navegação.

Se os fragmentos estiverem passando objetos complexos como argumentos, considere refatorar seu código primeiro, de forma que permita armazenar e buscar esses objetos do a camada de dados. Consulte o repositório Now in Android para exemplos.

Limitações

Esta seção descreve as limitações atuais do Navigation Compose.

Migração incremental para o Navigation Compose

No momento, não é possível usar o Navigation Compose enquanto usa fragmentos como e destinos no código. Para começar a usar o Navigation Compose, todos os Os destinos precisam ser elementos combináveis. Você pode acompanhar essa solicitação de recurso no Issue Tracker (link em inglês).

Animações de transição

A partir do Navigation 2.7.0-alpha01, há suporte para a configuração de As transições, que antes eram de AnimatedNavHost, agora são diretamente suportado em NavHost. Leia as notas da versão. para mais informações.

Saiba mais

Para ver mais informações sobre a migração para o Navigation Compose, consulte o seguinte recursos:

  • Codelab do Navigation Compose: aprenda os conceitos básicos do Navigation Compose com em um codelab prático.
  • Repositório Now in Android: um app Android totalmente funcional criado inteiramente com Kotlin e Jetpack Compose, que segue o design do Android e práticas recomendadas de desenvolvimento e inclui o Navigation Compose.
  • Como migrar o app Sunflower para o Jetpack Compose: uma postagem do blog (em inglês) documenta a jornada de migração do app de exemplo Sunflower do Views para o Compose, que também inclui a migração para o Navigation Compose.
  • Jetnews para cada tela: uma postagem do blog que documenta a refatoramento e migração da amostra do Jetnews para oferecer suporte a todas as telas com Jetpack Compose e Navigation Compose.