導航地圖互動的最佳做法

本頁說明在應用程式中與導航地圖互動的最佳做法。

盡可能使用 NavigationFragment,而非 NavigationView

NavigationFragment 會包裝 NavigationView,並自動處理生命週期回呼,因此您不必自行管理。這種做法較不容易出錯,建議您在應用程式中使用這種導覽方式。使用 NavigationFragment 時,請勿直接叫用 NavigationView 生命週期事件。

如果使用 NavigationView,請在叫用生命週期方法時嚴格遵守順序

NavigationView 會代管 Navigation 地圖,並密切追蹤 Android 活動和片段的生命週期事件,在叫用這些生命週期事件時採取特定動作。NavigationView 會在 NavigationView#onCreate 和 NavigationView#onStart 上執行多次初始化,並在 NavigationView#onStop 和 NavigationView#onDestroy 上執行清理作業,以及處理其他生命週期事件時執行。

NavigationView 生命週期方法與 Android 活動或片段的生命週期方法意義相同。舉例來說,NavigationView 的 onCreate 大致會轉譯為 Android 活動或片段的生命週期回呼,並由這些回呼叫用。由於 NavigationView 生命週期回呼是以 Android 生命週期回呼為基礎,且兩者會以相同順序叫用,因此必須嚴格排序這些 NavigationView 方法。否則可能會發生記憶體洩漏、UI 錯誤、位置資訊未更新等問題。

如要進一步瞭解 Android 活動生命週期,請參閱 Android 開發人員說明文件中的「活動生命週期概念」一節。

下表顯示在指定生命週期方法之後,應呼叫其他生命週期方法的時間:

生命週期方法 在活動生命週期中呼叫的位置 在下列生命週期方法後叫用
onConfigurationChanged() 當 UI 處於前景且設定變更時,系統會叫用此函式。 一律在 onStart() 之後
onTrimMemory() 活動在背景時會叫用此方法。 一律在 onPause() 之後
onSaveInstance() 在活動遭到刪除前呼叫。 一律在 onStop() 之後

請勿多次呼叫這些生命週期方法,但要先呼叫對應的關閉方法。此外,請注意,如果部分 Android 生命週期回呼是由應用程式本身管理,且 NavigationView 是在建立或啟動後新增至片段,應用程式應依正確順序呼叫特定方法,才能正確初始化 Navigation SDK。

如需使用這些方法的其他指引,請參閱 Navigation SDK 示範應用程式。

如果使用 NavigationView,請從活動或片段叫用生命週期事件,而非兩者都叫用

如要維持生命週期方法的嚴格順序,請從活動或片段生命週期回呼中叫用這些事件,這些回呼會依序接收這些事件。這種做法可確保應用程式不必在片段和活動之間協調,也不會導致重複呼叫。

從 SupportNavigationFragment 更新至 NavigationFragment

從 Navigation SDK 8.0.0 版開始,NavigationFragment 會取代已淘汰的 SupportNavigationFragment,做為即時路況導航和地圖顯示的標準片段容器。

NavigationFragment 維持與 SupportNavigationFragment 完整的 API 同位性。 如要更新應用程式,請在 XML 版面配置檔案和原始碼匯入項目中,將 SupportNavigationFragment 替換為 NavigationFragment。所有方法簽章和 getSupportFragmentManager() 呼叫都會保持不變。

更新版面配置 XML

在版面配置 XML 檔案中,將 SupportNavigationFragment 替換為 NavigationFragment:

變更前 (7.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" />

變更後 (8.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 (建議用於代管片段),請更新 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() 查詢片段:

變更前 (7.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
  }
}
    

變更後 (8.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 的所有公開方法、監聽器介面和自訂 UI 控制項,且方法簽章相同 (包括 getMapAsync()、getNavigator()、setEtaCardEnabled() 和 setStylingOptions())。