Android Kotlin基礎講座 03.3: 外部のアクティビティを起動する

タスク:Sage Argsプラグインをセットアップし利用する

ユーザーがAndroidTriviaアプリ内からゲーム結果をシェアできるようにする前に、あるフラグメントから別のフラグメントに引数を渡せるようにする必要があります。このやり取りでのバグを避け、型安全にするために、Safe Argsと呼ばれるGradleプラグインを使います。このプラグインはNavDirectionクラスを生成します。コードにこれらのクラスを追加していきます。

この記事の後半のタスクでは、フラグメント間で引数のやり取りをするためにNavDirectionクラスを利用します。

Safe Argsプラグインが必要な理由

これからフラグメント間でデータのやり取りを頻繁にする必要があります。あるフラグメントから別のフラグメントにデータを渡す方法の一つとして、Bundleクラスのインスタンスを使う手法があります。Android Bundleはキーバリューストア(KVS)です。

ディクショナリー、または連想配列としても知られるKVSは独自のキー(string)を使用して関連した値を取り出すデータ機構です。例として以下のようなものがあります。

キー
“name”“Anika”
“favorite_weather”“sunny”
“favorite_color”“blue”

これから開発するアプリはBundleを使ってフラグメントAからフラグメントBにデータを渡すことができます。例えば、フラグメントAはbundleを作成し、キーと値のペアとして情報を保存します。それからBundleをフラグメントBに渡します。フラグメントBはキーを使ってBundleからキーに対応する値を取り出します。この技術は機能はしますが、コンパイルはできるけど動作時にエラーを起こす可能性があるコードを生み出します。

起こりうるエラーには以下のようなものがあります:

  • 型不一致エラー:例として、フラグメントAがstringを送ったのにフラグメントBがintegerをbundleに要求した場合、その要求に対してはデフォルトの値の0が返されます。0は有効な値であるため、このような型不一致問題ではコンパイル時にはエラーは投げられません。しかし、ユーザーがアプリを実際に起動した際に、このエラーによってアプリの予期しない挙動やクラッシュを引き起こす可能性があります。
  • ミッシングキーエラー:フラグメントBがbundleにセットされていない値を要求した場合、nullが返されます。これもまたコンパイル時にはエラーが投げられませんが、起動時に問題を起こす可能性があります。

こういったエラーはAndroid Studioでのアプリコンパイル時にキャッチして、アプリを製品化する前に解消しておきたいものです。言い換えれば、ユーザーがこれらのエラーに遭遇する前に、開発中にエラーをキャッチする必要があります。

これらの問題を解決する手助けとして、AndroidのNavigation Architecture ComponentにはSafe Argsと呼ばれる特色が含まれています。Safe Argsは本来アプリが動作するまで表に出ることのないエラーをコンパイル時に検出するためのコードやクラスを生成するGradleプラグインです。

ステップ1:スターターアプリを開いて起動する

  1. この記事用のAndroidTriviaスターターアプリを入手してください。
  • 前回の記事を完了している場合、それを引き継いでお使いいただけます。
  • 前回の記事を完了していない場合、AndroidTriviaNavigationからダウンロードして利用してください。

Android Studioからアプリを起動します。

  1. アプリをAndroid Studioで開いてください。
  2. アプリを実機、またはエミュレーターで起動してください。アプリはナビゲーションドロワー、タイトル画面でのオプションメニュー、左上部にアップボタンがついたトリビアゲームです。
  3. ゲームをプレイして内容を理解してください。三つの問題に正確に答えてゲームクリアとなると、以下のCongratulations画面が表示されます。



    この記事では、共有アイコンをCongratulations画面のトップに追加します。共有アイコンを使ってユーザーはゲーム結果をEメールやテキストでシェアすることができます。

ステップ2:プロジェクトにSage Argsを追加する

  1. Android Studioでプロジェクトレベルのbuild.gradleファイルを開いてください。
  2. navigation-safe-agrs-gradle-plugin依存関係を以下のように追加してください。
// Adding the safe-args dependency to the project Gradle file
dependencies {
   ...
classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"

}
  1. アプリレベルのbuild.gradleファイルを開いてください。
  2. ファイルの最上部、他のプラグインのあとにapply plugin文をandroidx.navigation.safeargsプラグインと共に追加してください。
// Adding the apply plugin statement for safeargs
apply plugin: 'androidx.navigation.safeargs'
  1. プロジェクトを再ビルドしてください。もし追加のビルドツールをインストールするように促されたら、それらをインストールしてください。

これでプロジェクトにNavDirectionクラスが生成されました。

Safe Argsplugインはそれぞれのフラグメントに対してNavDirectionクラスを生成します。それらのクラスはアプリ内の全てのアクションからのナビゲーションを表します。

例として、GameFragmentはここまででGameFragmentDirectionsクラスを生成しています。GameFragmentDirectionsクラスを利用して型安全の引数をゲームフラグメントや他のフラグメント間で受け渡しすることができます。

生成されたファイルを見るには、Project > Android内のgeneratedJavaフォルダーを確認してください。

注意:NavDirectionクラスは編集しないでください。これらのクラスはプロジェクトがコンパイルされる際に再び生成され、編集した箇所は失われます。

ステップ3:ゲームフラグメントにNavDirectionクラスを追加する

このステップでは、GameFragmentDirectionsクラスをゲームフラグメントに追加します。このコードは後に引数をGameFragmentとゲーム状況フラグメント(GameWonFragmentとGameOverFragment)間でやり取りするために使います。

  1. javaフォルダー内のGameFragment.ktファイルを開いてください。
  2. onCreateView()メソッド内のゲームクリア条件文(“We’ve won!”)の部分を見てください。NavController.navigate()メソッドに渡されている引数を変更します。
    game-wonのアクションIDとGameFragmentDirectionsクラスのactionGameFragmentToGameWonFragment()を利用しているIDを置き換えてください。

    ここまでの条件文は以下のようになります。次のタスクでactionGameFragmentToGameWonFragment()にパラメーターを追加します。
// Using directions to navigate to the GameWonFragment
view.findNavController()
        .navigate(GameFragmentDirections.actionGameFragmentToGameWonFragment())
  1. 同様に、ゲーム失敗条件文(“Game over!”)の部分も以下のように書き換えてください。
// Using directions to navigate to the GameOverFragment
view.findNavController()
        .navigate(GameFragmentDirections.actionGameFragmentToGameOverFragment())