导航地图互动最佳实践

本页介绍了在应用中与导航地图互动的最佳实践。

尽可能使用 NavigationFragment 而不是 NavigationView

NavigationFragment 封装了 NavigationView 并自动处理其生命周期回调,因此您无需自行管理这些回调。这种方法不易出错,是建议在应用中使用导航的方式。使用 NavigationFragment 时,请勿直接调用 NavigationView 生命周期事件。

如果使用 NavigationView,请在调用生命周期方法时使用严格的排序

NavigationView 托管导航地图,并像 Android activity 和 fragment 一样密切关注生命周期事件,在这些生命周期事件被调用时采取特定操作。NavigationView 会在 NavigationView#onCreate 和 NavigationView#onStart 上执行多次初始化,在 NavigationView#onStop 和 NavigationView#onDestroy 上执行清理,以及在处理其他生命周期事件时执行初始化和清理。

NavigationView 生命周期方法的含义与 Android activity 或 fragment 的相同。例如,NavigationView 的 onCreate 大致相当于 Android activity 或 fragment 的生命周期回调,并且应由这些回调来调用。由于 NavigationView 生命周期回调基于 Android 生命周期回调,并且以与 Android 生命周期回调相同的顺序调用,因此必须严格按照顺序调用这些 NavigationView 方法。否则,您可能会遇到内存泄漏、界面错误、位置信息未更新等问题。

如需详细了解 Android activity 生命周期,请参阅 Android 开发者文档中的 activity 生命周期概念部分。

下表显示了在指定生命周期方法之后,应何时调用其他生命周期方法:

生命周期方法 在 activity 生命周期的哪个阶段调用 在哪个生命周期方法之后调用
onConfigurationChanged() 当界面位于前台且配置发生更改时调用。 始终在 onStart() 之后
onTrimMemory() 当 activity 处于后台时调用。 始终在 onPause() 之后
onSaveInstance() 在 activity 被销毁之前调用。 始终在 onStop() 之后

请勿在未先调用相应关闭方法的情况下多次调用这些生命周期方法。此外,请注意,如果这些 Android 生命周期回调中的某些回调由应用本身管理,并且在创建或启动后将 NavigationView 添加到 fragment,则应用应按正确的顺序调用特定方法,以正确初始化 Navigation SDK。

如需有关使用这些方法的更多指导,请参阅 Navigation SDK 演示应用。

如果使用 NavigationView,请从 activity 或 fragment(而非两者)调用生命周期事件

为了保持生命周期方法的严格顺序,请从 activity 或 fragment 生命周期回调中调用这些事件,这些回调会按顺序接收这些事件。这种方法可确保应用无需在 fragment 和 activity 之间进行协调,也不会导致重复调用。

从 SupportNavigationFragment 更新到 NavigationFragment

从 Navigation SDK v8.0.0 开始,NavigationFragment 取代了已弃用的 SupportNavigationFragment,成为精细导航和地图显示的标准 fragment 容器。

NavigationFragment 与 SupportNavigationFragment 保持完全的 API 对等性。 如需更新应用,请在 XML 布局文件和源代码导入中将 SupportNavigationFragment 替换为 NavigationFragment。所有方法签名和 getSupportFragmentManager() 调用都保持不变。

更新布局 XML

将布局 XML 文件中的 SupportNavigationFragment 替换为 NavigationFragment:

之前(v7.x 及更低版本):

<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" />

之后(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" />

如果您的应用使用 FragmentContainerView(建议用于托管 fragment),请更新 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" />

更新应用代码

替换 Java 或 Kotlin 代码中的导入和类转换。由于这两个类都扩展了 androidx.fragment.app.Fragment,因此请继续使用 getSupportFragmentManager() 查找 fragment:

之前(v7.x 及更低版本):

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
  }
}
    

之后(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
  }
}
    

API 对等性

您无需进行任何其他行为更改或重构代码。 NavigationFragment 支持 SupportNavigationFragment 中的所有公共方法、监听器接口和自定义界面控件,这些方法具有相同的方法签名(包括 getMapAsync()、getNavigator()、setEtaCardEnabled() 和 setStylingOptions())。