【2024年4月】弊社では、基本リモートワークで一緒に成長してくださるメンバーを広く募集させていただいております。 詳細はこちら

【Android】KotlinにおけるActivity、Fragment間のデータの受け渡し(Bundle、ViewModel)を簡単に実装する方法!

【Android】KotlinにおけるActivity、Fragment間のデータの受け渡し(Bundle、ViewModel)を簡単に実装する方法!
すだ

みなさまこんにちは〜!
メモリアインクのすだです。

本日は、
KotlinでBundle、ViewModelを使用した
画面遷移時のデータの受け渡しについて コードを交えて解説していきます!

この記事を読んでわかること…
・Bundleを使用したデータの受け渡し
・ViewModelを使用したデータデータの受け渡し

目次

環境

  • Kotlin (ver 1.9.0)
  • Android Studio (Giraffe | 2022.3.1 Patch 3)

Bundleを使用したデータの受け渡し

Bundleとは?

BundleはAndroid SDKの一部であり、キーと値のペアの集まりを保持することができるクラスです。

「データを入れる箱」と考えるとイメージしやすいでしょう。
この箱を使って、アプリの異なる部分間でデータを運ぶことができます。

ここでいう「キー」とは文字列型の識別子であり、
「値」とは保存したいデータ(文字列、整数、真偽値、オブジェクトなど)を指します。

Bundleの使い方

  • キーとバリューのペア
    Bundleを使用する際には、まずデータを「キーとバリューのペア」としてBundleに追加します。
    このキーは、後でデータを取り出す際の識別子として機能します。
    例えば、ユーザー名を保存する場合、キーとして”user_name”、バリューとして実際のユーザー名を使用します。
  • データの取り出し
    データを受け取る側では、Bundleから先ほどセットしたキーを使ってデータを取り出します。
    このプロセスにより、正確に必要なデータを簡単に取得できます。
  • 一方向のデータ交換に向いている
    Bundleで渡されるデータは基本的に読み取り専用で、受け取ったデータを変更することは想定されていません。
    そのため、データを受け渡したいだけで、その後で受け取ったデータを書き換える必要がない場合に最適な方法です。

コード例

では早速、実装を行なっていきましょう〜!

ActivityからActivityへ
新しいActivityを開始する際に、IntentにBundleを添付してデータを受け渡します。

Activity 1(データ送信側)

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val intent = Intent(this, SecondActivity::class.java)

        val bundle = Bundle()
     bundle.putString("key", "value")

        intent.putExtras(bundle)

        startActivity(intent)
    }
}

解説

val bundle = Bundle()
bundle.putString(“key”, “value”)

Bundleオブジェクトを作成し、ドット繋ぎの記法でデータを追加します。

putStringは文字列のデータを追加する際に使用されるものですが、
他にも、putInt(整数)、putBoolean(真偽値)などなど
データ方に合わせて様々なメソッドが用意されています。

intent.putExtras(data)

そして、putExtrasメソッドを使用して IntentにBundle(データを入れる箱)を添付しています。

Activity 2(データ受け取り側)

class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)

        val bundle = intent.extras

        val value = bundle?.getString("key", "デフォルト値")
    }
}

解説

val bundle = intent.extras

2つめのActivityが開始された際に、前のActivityから送られてきた追加のデータ(extras)を取得しています。
extrasプロパティ(オブジェクトの状態を保持できる箱)によってこのBundleにアクセスして、
そこに含まれるデータを取り出す という仕組み。

bundle?.getString(“key”, “デフォルト値”)

ここで、取得したBundleから特定のデータを取り出しています。
キー(この例では "key")に対応する値を「文字列として」取得するというものです。

Activity(Fragment)からFragmentへ
この場合は、Fragmentを生成する際に、setArguments()メソッドを使用してデータをセットします。

Activity 1(データ送信側)

class MyActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_my)

        val bundle = Bundle()
     bundle.putString("key", "value")

     val subFragment = SubFragment()
     subFragment.setArguments(bundle)

        supportFragmentManager.beginTransaction()
            .replace(R.id.fragment_container, subFragment)
            .commit()
    }
}

解説

val subFragment = SubFragment()
subFragment.setArguments(bundle)

新しいFragmentインスタンスを生成し、
setArguments()メソッドを使用してBundleをセットしています。

Fragment 1(データ受け取り側)

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val data = arguments?.getString("key", "デフォルト値")
}

解説

arguments?.getString(“key”, “デフォルト値”)

argumentsというプロパティを使って、
FragmentにセットされたBundleオブジェクトを参照することができます。

すだ

画面遷移のパターンによって、少し書き方が変わってきますね!
慣れるとすぐに認識できるようになるはずです!

ViewModelを使用したデータの受け渡し

ViewModelとは?

ViewModelは、UIのデータを管理するためのコンポーネントです。

たとえば、画面に行って戻ってきたりすると、画面に表示されている情報が消えてしまうことがあります。
これは、「アプリが新しく画面を作り直すから」です。
ここでViewModelを使用することによって画面の情報を「忘れずに保持」しておくことができます。

これにより、データの再読み込みや再計算を防ぎ、アプリのパフォーマンスを向上させることができるのです。

ViewModelの使い方

  • ライフサイクルをほとんど考えなくて良い
    アプリ画面の状態がどう変わろうと、ViewModelはデータを保持し続けてくれるという特性があります。
    アプリを完全に閉じたり、スマホのタスクリストからアプリを消したりすると、
    onClearedメソッドが呼ばれデータが消し去られます。
  • データの橋渡しのようなイメージ
    ViewModelはアプリのUI(ユーザーインターフェース)とデータの間で橋渡しをする役割を果たします。
    UIの入力を受けてデータを更新したり、データの変更をUIに反映させたりするシーンで使われることが多いです。
  • Activity間の画面遷移では使わない
    ViewModelは特定のActivity(またはFragment)に「紐付け」られています。
    つまり、ViewModelはそのActivityが持っているデータや状態を管理するためのものであり、
    Activityが破棄されるとViewModelもその役目を終えます。

    複数のFragmentが同じActivityに紐づいている場合、
    Fragment間でViewModelを共有でき、ViewModelを用いて画面遷移時のデータの共有を実現できるのです。
【Android】KotlinにおけるActivity、Fragment間のデータの受け渡し(Bundle、ViewModel)を簡単に実装する方法!

コード例

では早速実装してみましょう!

Fragment1で入力された文字列を、ボタン押下時にFragment2へ送信します。

2つのFragmentのほかに、共有するデータを保持するViewModelを定義します。

SharedViewModel.kt

class SharedViewModel : ViewModel() {
    val message = MutableLiveData<String>()
}

解説

ただのLiveDataは変更不可ですが、
MutableLiveDataは、値が変更可能なLiveDataです。

LiveDataとは、データの値を保持し、その値の変更を監視することができる箱です。

UIの部品は、LiveDataに格納されているデータの変更を監視し、
データが変更されると自動的に更新されます。
(例えば、天気予報が晴れから雨に変わったとき、アプリの画面に「中身変わったよ〜」と教えてくれる
みたいなイメージですね!)

Fragment 1 (データ送信側)

class FirstFragment : Fragment() {

    private val sharedViewModel: SharedViewModel by activityViewModels()

    override fun onCreateView(){
        // 省略
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        sendButton.setOnClickListener {
            val inputMessage = messageEditText.text.toString()
            sharedViewModel.input_message.value = inputMessage
        }
    }
}

解説

sharedViewModel.message.value = inputMessage

ユーザーが入力したメッセージを共有ViewModelに設定します。
ここではデータにinput_messageという名前をつけて、value値にセットしています。

Fragment 2 (データ受け取り側)

class SecondFragment : Fragment() {

    private val sharedViewModel: SharedViewModel by activityViewModels()

    override fun onCreateView() {
        // 省略
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        sharedViewModel.input_message.observe(viewLifecycleOwner, Observer { message ->
            messageTextView.text = message
        })
    }
}

解説

sharedViewModel.input_message

先ほどViewModelにセットしたデータにアクセスしています。

.observe(viewLifecycleOwner, Observer { message ->
messageTextView.text = message
})

observeメソッドは、データの監視を開始するためのもの
共有されているデータに設定や変更があったときに、
何かアクション(この例ではテキストビューの更新)を行うように設定しています。

viewLifecycleOwnerは、このフラグメントのビューのライフサイクルを監視するオブジェクト。
これにより、フラグメントの画面が表示されている間だけデータの変更を監視し、
画面がなくなれば自動的に監視を停止します。
これは、無駄な処理を避け、アプリのパフォーマンスを保つために重要です。

Observer { ... }は、データに変更があったときに実行されるアクションを定義します。
この部分で「変更があったら、この処理をしてね」とアプリに教えています。

最終的に、messageTextViewという名前のテキストビューにデータを表示しています。

すだ

Bundleとは考え方が大きく異なりますね!
あまり複雑でないデータの共有には、ViewModelを使うのもよさそうですね〜!

まとめ

いかがでしたでしょうか〜!

データの受け渡しは、開発を進めていく中で必ず実装するシーンがあるかと思いますので
ぜひ使い方をマスターしてください!

すだ

技術者としてのキャリアパスを次のレベルへと進めたい皆様、
未経験からIT・Webエンジニアを目指すなら【ユニゾンキャリア】
を通じて、
自分の市場価値をさらに向上させてみませんか?

それではまた次の記事でお会いしましょう!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

目次