ナビゲーション マップ操作のベスト プラクティス

このページでは、アプリでナビゲーション マップを操作する際のベスト プラクティスについて説明します。

可能な限り NavigationView ではなく NavigationFragment を使用する

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 v8.0.0 以降では、NavigationFragment が、非推奨の SupportNavigationFragment に代わって、ターンバイターン ナビゲーションと地図表示の標準のフラグメント コンテナになります。

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(フラグメントのホスティングに推奨)を使用している場合は、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() を含む)でサポートします。