Práticas recomendadas para interação de navegação com o mapa

Nesta página, explicamos as práticas recomendadas para interagir com o mapa de navegação no seu app.

Use NavigationFragment em vez de NavigationView, sempre que possível

O NavigationFragment envolve o NavigationView e processa automaticamente os callbacks do ciclo de vida, para que você não precise gerenciá-los. Essa abordagem é menos propensa a erros e é a maneira recomendada de usar a navegação no app. Ao usar NavigationFragment, não invoque eventos de ciclo de vida de NavigationView diretamente.

Se estiver usando NavigationView, use a ordenação estrita ao invocar métodos de ciclo de vida.

O NavigationView hospeda o mapa de navegação e segue de perto os eventos de ciclo de vida, como atividades e fragmentos do Android, realizando ações específicas quando esses eventos são invocados. O NavigationView executa várias inicializações em NavigationView#onCreate e NavigationView#onStart, limpezas em NavigationView#onStop e NavigationView#onDestroy, além de outros eventos de ciclo de vida.

Os métodos de ciclo de vida do NavigationView têm o mesmo significado que têm para atividades ou fragmentos do Android. Por exemplo, onCreate de NavigationView é mais ou menos traduzido e precisa ser invocado por callbacks do ciclo de vida da atividade ou do fragmento do Android. Como os callbacks do ciclo de vida do NavigationView são baseados e invocados na mesma ordem que os callbacks do ciclo de vida do Android, é necessário ordenar estritamente esses métodos do NavigationView. Caso contrário, você pode ter vazamentos de memória, erros de interface, localização não atualizada e outros problemas.

Para mais informações sobre o ciclo de vida da atividade do Android, consulte a seção Conceitos do ciclo de vida da atividade na documentação para desenvolvedores Android.

A tabela a seguir mostra quando outros métodos de ciclo de vida precisam ser invocados, após métodos de ciclo de vida especificados:

Método de ciclo de vida Invocado em que parte do ciclo de vida da atividade Invocado após qual método de ciclo de vida
onConfigurationChanged() Invocado quando a interface está em primeiro plano e a configuração muda. Sempre depois de onStart()
onTrimMemory() Invocado quando uma atividade está em segundo plano. Sempre depois de onPause()
onSaveInstance() Invocado antes que uma atividade seja destruída. Sempre depois de onStop()

Não chame esses métodos de ciclo de vida várias vezes sem chamar o método de fechamento correspondente primeiro. Além disso, se alguns desses callbacks do ciclo de vida do Android forem gerenciados pelo próprio app e o NavigationView for adicionado ao fragmento após a criação ou o início, o app precisará chamar os métodos específicos na ordem adequada para inicializar corretamente o SDK de navegação.

Para mais orientações sobre como usar esses métodos, consulte o app de demonstração do SDK de navegação.

Se estiver usando NavigationView, invoque eventos de ciclo de vida da atividade ou do fragmento, não de ambos.

Para manter a ordem estrita dos métodos de ciclo de vida, invoque esses eventos nos callbacks do ciclo de vida da atividade ou do fragmento, que recebem esses eventos em ordem. Essa abordagem garante que os apps não precisem coordenar entre fragmentos e atividades e causar chamadas duplicadas.

Atualização de SupportNavigationFragment para NavigationFragment

A partir do SDK Navigation v8.0.0, NavigationFragment substitui o SupportNavigationFragment descontinuado como o contêiner de fragmento padrão para navegação guiada e exibição de mapa.

O NavigationFragment mantém total paridade de API com o SupportNavigationFragment. Para atualizar o app, substitua SupportNavigationFragment por NavigationFragment nos arquivos de layout XML e nas importações de código-fonte. Todas as assinaturas de método e chamadas getSupportFragmentManager() permanecem idênticas.

Atualizar o XML de layout

Substitua SupportNavigationFragment por NavigationFragment nos arquivos XML de layout:

Antes (v7.x e anteriores):

<fragment
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/navigation_fragment"
    android:name="com.google.android.libraries.navigation.SupportNavigationFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Depois (v8.0.0+):

<fragment
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/navigation_fragment"
    android:name="com.google.android.libraries.navigation.NavigationFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Se o app usa FragmentContainerView (recomendado para hospedar fragmentos), atualize o atributo android:name:

<androidx.fragment.app.FragmentContainerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/navigation_fragment"
    android:name="com.google.android.libraries.navigation.NavigationFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Atualizar o código do aplicativo

Substitua as importações e as transmissões de classe no código Java ou Kotlin. Como as duas classes estendem androidx.fragment.app.Fragment, continue usando getSupportFragmentManager() para procurar o fragmento:

Antes (v7.x e anteriores):

Java

import com.google.android.libraries.navigation.SupportNavigationFragment;

public class MainActivity extends AppCompatActivity {
  private SupportNavigationFragment mNavFragment;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mNavFragment = (SupportNavigationFragment) getSupportFragmentManager()
        .findFragmentById(R.id.navigation_fragment);
  }
}
    

Kotlin

import com.google.android.libraries.navigation.SupportNavigationFragment

class MainActivity : AppCompatActivity() {
  private lateinit var navFragment: SupportNavigationFragment

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    navFragment = supportFragmentManager
        .findFragmentById(R.id.navigation_fragment) as SupportNavigationFragment
  }
}
    

Depois (v8.0.0+):

Java

import com.google.android.libraries.navigation.NavigationFragment;

public class MainActivity extends AppCompatActivity {
  private NavigationFragment mNavFragment;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mNavFragment = (NavigationFragment) getSupportFragmentManager()
        .findFragmentById(R.id.navigation_fragment);
  }
}
    

Kotlin

import com.google.android.libraries.navigation.NavigationFragment

class MainActivity : AppCompatActivity() {
  private lateinit var navFragment: NavigationFragment

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    navFragment = supportFragmentManager
        .findFragmentById(R.id.navigation_fragment) as NavigationFragment
  }
}
    

Paridade de API

Não é necessário fazer outras mudanças de comportamento nem reestruturar o código. O NavigationFragment é compatível com todos os métodos públicos, interfaces de listener e controles de interface personalizados do SupportNavigationFragment com assinaturas de método idênticas (incluindo getMapAsync(), getNavigator(), setEtaCardEnabled() e setStylingOptions()).