3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JetpackComposeの「Navigation 3」ってなんだ? その1

Last updated at Posted at 2025-06-05

Jetpack Compose向けナビゲーションライブラリ「Jetpack Navigation 3」のalpha版が公式から先日リリースされました

はじめに

この記事では「Jetpack Navigation 3」の基本的な使い方、従来の公式のNavigationとの違いについて検証します

dependencies {
  // 執筆バージョン
  implementation "androidx.navigation3.navigation3-runtime:1.0.0-alpha03"
  implementation "androidx.navigation3.navigation3-ui:1.0.0-alpha03"
}

とりあえず基本形は?

// Navigation 3
@Composable
fun Main() {
  val startKey: String = remember { "HOME" }
  val backStack: SnapshotStateList<String> = remember {
    mutableStateListOf(startKey)
  }
  NavDisplay(
    backStack = backStack
  ) { key: String ->
    when (key) {
      "HOME" -> NavEntry("HOME") {
        Column {
          Text("ここはホーム画面です")
          Button(
            onClick = { backStack.add("LIBRARY") }
          ) {
            Text("クリックしてライブラリ画面に遷移する")
          }
        }
      }
      "LIBRARY" -> NavEntry("LIBRARY") {
        Text("ここはライブラリ画面です")
      }
      else -> error("不明な画面です")
    }
  }
}

こんな感じです
SnapshotStateListというList向けMutableStateでバックスタックの状態をComposableのサイクルで監視し、バックスタックをリスト操作すると画面遷移します

従来の公式のNavigationとの違いは?

// 従来のNavigation
@Composable
fun Main() {
  val startKey: String = remember { "HOME" }
  val controller = rememberNavController()
  NavHost(
    navController = controller,
    startDestination = startKey
  ) {
    composable("HOME") {
      Column {
        Text("ここはホーム画面です")
        Button(
          onClick = { controller.navigate("LIBRARY") }
        ) {
          Text("クリックしてライブラリ画面に遷移する")
        }
      }
    }
    composable("LIBRARY") {
      Text("ここはライブラリ画面です")
    }
  }
}

大きな違いはバックスタックのリストが隠蔽されているかです
Navigation3ではバックスタックのリスト操作をアプリ開発者に委ねることとなりました

他の違いとして、この記事では説明を省きますが、アダプティブレイアウトを構築するための便利な機能「シーン」がNavigation3に備わっています

Navigation 3 は自分でバックスタックをリスト操作する

とはいっても基本は

// ホーム画面に移動
backStack.add("HOME")

// ひとつ前の画面に戻る
backStack.removeAt(backStack.lastIndex)

のふたつだけです

このふたつを駆使しながら、Navigation3で色々と挑戦していきましょう

メインの話はここまでです

(補足)挑戦の前に、上記の基本形を実用形に

まず、上記の基本形はバックスタックをrememberSaveableで状態保持しておらず、Androidライフサイクルのアクティビティの破棄によりバックスタックが初期化されてしまいます
これを修正します

修正案1 Navigation 3にて用意されているrememberNavBackStackを使う

@Serializable
data object Home: NavKey
@Serializable
data object Library: NavKey

@Composable
fun Main() {
  val startKey = remember { Home }
  val backStack: SnapshotStateList<NavKey>
      = rememberNavBackStack(startKey)
  NavDisplay(
    backStack = backStack,
    entryProvider = entryProvider {
      entry<Home> { key: Home -> /* ホーム画面 */ }
      entry<Library> { key: Library -> /* ライブラリ画面 */ }
    }
  )

rememberNavBackStackは内部でrememberSaveableによりバックスタックを状態保持しているので、これで完了です
ついでにentryProviderという、従来のNavigationのように使える関数も使ってみました、お手軽です

修正案2 バックスタックをrememberSaveableにて保存可能なオブジェクトに変換する

@Serializable
sealed interface Key

@Serializable
data object Home: Key
@Serializable
data object Library: Key

@Composable
fun Main() {
  val startKey = remember { Home }
  val backStack: SnapshotStateList<Key> = rememberSaveable(
    saver = Saver<SnapshotStateList<Key>, SavedState>(
      saver = { mutableStateList: SnapshotStateList<Key> ->
        encodeToSavedState(mutableStateList.toList())
      },
      restore = { savedState: SavedState ->
        decodeFromSavedState<List<Key>>(savedState)
            .toMutableStateList()
      }
    )
  ) { mutableStateListOf(startKey) }
  NavDisplay(
    backStack = backStack
  ) { key: Key ->
    when (key) {
      Home -> NavEntry(Home) {
        /* ホーム画面 */
      }
      Library -> NavEntry(Library) {
        /* ライブラリ画面 */
      }
    }
  }
}

sealed interfaceは基底クラスのサブクラスの型を保持したままシリアライズとデシリアライズをするので上記のように書けます
(詳しくはkotlinx serialization の公式ドキュメントを読んでください)
バックスタックをrememberSaveableにて保持可能なオブジェクトのSavedStateに変換しました

またこの修正案では、sealed interfaceの最大の特徴のwhen文にて、サブクラスの一覧を静的に取得しIDEの機能で自動的に列挙できる便利な機能を活用できます
画面を作ったのにNavDisplayに登録し忘れたなんてミスはコンパイラが注意してくれるのでなくなります
個人的にはこちらの修正案のほうが好きです

総括

この記事では「Jetpack Navigation 3」の基本的な使い方、従来のNavigationとの大きな違いについて検証し執筆しました

また数日中にNavigation3に関する記事を書こうと考えてますので、よろしくお願いします

参考

・ Android Developers Blog : Announcing Jetpack Navigation 3

・ AndroidX Navigation3 : Overview

・ AndroidX Navigation3 : リリースページ

・ AndroidX Navigation3 : 公式サンプル

License

Copyright 2025 oikvpqya Yuya
 
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?