導航地圖互動的最佳做法

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

盡可能使用 NavigationFragment,而非 NavigationView

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

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

NavigationView 會託管導覽地圖,並密切追蹤 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" />

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

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