okuzawatsの日記

モバイルアプリケーション開発の沼💀

[Android] Fragmentに値を渡す

profile

書いている人 モバイルアプリケーションアーキテクト(Android)として働いています。モバイルアプリケーションのアーキテクチャ、自動テスト、CI/CDに興味があります。もっと詳しく

Navigation Safe Argsを使わない場合と使う場合に分けて書きます。

Navigation Safe Argsを使わずにFragmentに値を渡す時は、Bundleを使って渡します。Fragmentのインスタンスを生成するstaticなメソッドを作るのは良くあるパターンだと思いますが、この時にFragmentのargumentsにBundleをセットします。

companion object {
    private const val ARG_TEXT = "arg_text"

    fun newInstance(text: String) = MainFragment()
        .apply {
            arguments = Bundle().apply {
                putString(ARG_TEXT, text)
            }
        }
}

Bundleから値を取り出す時は、 by lazy の中で取り出すのが個人的には気に入っています。

private val text: String by lazy {
    arguments?.getString(ARG_TEXT) ?: ""
}

必ずFragmentに値が渡ってくるのであれば、 arguments の代わりに requireArguments が使えます。つまり、 requireArguments().getString(ARG_TEXT) というように書けます。

Navigation Safe Argsを使って値を渡す方法について以下に示します。

app/build.gradle に追加します。

apply plugin: 'androidx.navigation.safeargs.kotlin'

build.gradle にも追加します。

buildscript {
        // Navigation Safe Args
        def nav_version = "2.1.0"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}

これだけだと「Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6」みたいな感じで怒られるので、さらに app/build.gradle に以下を追加します。

android {
    compileOptions {
        sourceCompatibility = 1.8
        targetCompatibility = 1.8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

Navigation Graphに argument を追加して、名前と型を指定します。 android:defaultValue="John Doe" のようにすればデフォルト値が設定できます。

<fragment
        android:id="@+id/output_fragment"
        android:name="com.okuzawats.helloworld.fragment.OutputFragment"
        android:label="fragment_output"
        tools:layout="@layout/fragment_output">

    <argument
        android:name="name"
        app:argType="string"/>

</fragment>

遷移元では、Actionに対象となる引数を渡します。一回、ビルドすると必要なクラスが生成されるかと思います。

val inputText = input_edit_text.text.toString()
val action = InputFragmentDirections.actionInputToOutput(inputText)
findNavController().navigate(action)

遷移先では、 navArgs()argument を取得し、プロパティ名で中に入っている値を取り出します。

private val args: OutputFragmentArgs by navArgs()

private val name: String by lazy {
    args.name
}

Related