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

このページでは、アプリで Navigation マップを操作するためのベスト プラクティスについて説明します。

可能な限り、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 以降では、ターンバイターン方式のナビと地図表示の標準フラグメント コンテナとして、非推奨の SupportNavigationFragment に代わり NavigationFragment が使用されます。

NavigationFragment は SupportNavigationFragment と同等の API を維持します。アプリを更新するには、XML レイアウト ファイルとソースコードのインポートで SupportNavigationFragment を NavigationFragment に置き換えます。すべてのメソッド シグネチャと getSupportFragmentManager() 呼び出しは同じままです。

レイアウト XML を更新する

SupportNavigationFragment をレイアウト XML ファイルの 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() を含む)でサポートしています。