ViewModelを使用してフラグメントとアクティビティ間で通信する方法

コミュニケーションは、開発者にとって最も重要なトピックの1つであり、さまざまな方法で行うことができます。しかし、最も簡単で最適化された方法でそれを行うことが課題です。静的フィールドを使用して実行できますが、メモリの問題が発生します。メモリの問題を避けるために、多くの開発者は次のようなことをします

(MainActivityとしてのアクティビティ).passDataToAnotherFragment()

この方法の問題は何ですか?フラグメントを特定のアクティビティにバインドし、再利用性を低下させます。次に、推奨される方法は何ですか?

Googleでは、インターフェイス(ViewModelの前)のドキュメントを使用することをお勧めします。このために、アクティビティクラスにインターフェイスを実装する必要があります。子フラグメントは、activityによって実装されたインターフェイスの参照を保持します。データはインターフェイスメソッドを介して渡されます。

インターフェイスを使用した通信のワークフロー

同じアクティビティの下に2つのフラグメントがあり、1つは数値を入力し、もう1つはdouble(2 x入力)を表示するという単純なシナリオを想定します。アクティビティにもメッセージが表示されます。入力はこのように123です。

どのくらいのコードを書く必要があり、どのくらいのシナリオを処理する必要があるか想像できますか。この記事はインターフェースの実装を示すのではなく、最も簡単なソリューションに関するものなので、詳細には触れません。ここで実装を見つけることができます。

簡単な方法

多くのシナリオを処理し、インターフェイスを実装することから私たちを救うために、ここにViewModelが来ます。 ViewModelクラスを作成し、フラグメントにインスタンスを作成するだけで、アクティビティスコープを使用して、アクティビティ自体を含むアクティビティのすべてのフラグメントで使用できるようにします。

ViewModelを使用した通信のワークフロー

ViewModelクラスを作成する

クラスSharedViewModel:ViewModel(){
    val inputNumber = MutableLiveData ()
}

入力フラグメントからデータを送信または渡すには、アクティビティスコープでViewModelを作成します。これを行うには、ViewModelProvides.of()メソッドの引数としてアクティビティ参照を渡す必要があります。いいえ、このようにViewModelオブジェクトにデータを渡すだけです

activity?.let {
    sharedViewModel = ViewModelProviders.of(it).get(SharedViewModel :: class.java)
}

et_input.addTextChangedListener(object:TextWatcher {
    fun afterTextChanged(p0:Editable?){}をオーバーライドします

    funをオーバーライドするbeforeTextChanged(p0:CharSequence ?, p1:Int、p2:Int、p3:Int){}

    オーバーライドonTextChanged(txt:CharSequence ?, p1:Int、p2:Int、p3:Int){
        txt?.let {
            var input = 0
            if(txt.toString()。isNotEmpty()){
                入力= txt.toString()。toInt()
            }

            sharedViewModel?.inputNumber?.postValue(input)
        }
    }

アクティビティでは、ViewModelのインスタンスを作成し、このような必要なデータを観察するだけです。

val sharedViewModel = ViewModelProviders.of(this).get(SharedViewModel :: class.java)

sharedViewModel.inputNumber.observe(this、Observer {
    それ?.let {
        //数字を使って何かをする
    }
})

では、出力フラグメントについてはどうでしょうか?出力フラグメントに対しても同様にデータを観察できます。ただし、アクティビティスコープでViewModelインスタンスを作成する必要があることに注意してください。作成しない場合、Androidは同じインスタンスを共有するのではなく、個別のインスタンスを作成し、データを取得しません。

出力フラグメントの場合、このようにします

activity?.let {
    val sharedViewModel = ViewModelProviders.of(it).get(SharedViewModel :: class.java)

    sharedViewModel.inputNumber.observe(this、Observer {
    それ?.let {
            //数字を使って何かをする
        }
    })
}

それでおしまい。ソースコードはこちらにあります。

StackOverflowディスカッション

ハッピーコーディング