[アンドロイド]分割-アクティブデータ転送


つうしん


ユーザイベントに対して適切な応答またはステータス情報(データ)の共有を行うためには、アクティビティと計画または計画の間に通信チャネルが存在する必要があります.すなわち、分割マネージャと分割マネージャに記載されているが、互いに独立していなければならない.そのため、私たちは直接互いの間で通信することはできず、通信チャネルを使用してデータを共有する方法で通信しなければならない.
プランニング・ライブラリには、ViewModelまたはFragment Result APIの2つの通信オプションがあります.推奨されるオプションは使用例によって異なります.永続的なデータを使用している場合は、ViewModelを使用する必要があります.Bundleに一度にデータを配置できる場合は、Fragment Result APIを使用することをお勧めします.次に、コードを見て、操作方法を理解しましょう.

ViewModelを使用したデータ転送


ViewModelオブジェクトはUIデータを格納および管理します.このため、ViewModelを使用して複数の計画間でデータを共有したり、ホストアクティビティと計画間でデータを共有したりすることができます.

ホストアクティビティとデータ転送


これは、ホストアクティビティのViewModelにアクセスするための方法です.まず、ViewModelクラスを作成します.

ViewModelクラス

class ItemViewModel : ViewModel() {
    private val mutableSelectedItem = MutableLiveData<Item>()
    val selectedItem: LiveData<Item> get() = mutableSelectedItem

    fun selectItem(item: Item) {
        mutableSelectedItem.value = item
    }
}
データは、MutableLiveData型の変形選択Itemに格納される.この値はselectedItemからアクセスできます.次に、アクティビティと計画にViewModelを作成し、計画にデータを格納(共有)し、アクティビティでデータにアクセス(使用)します.

アクティブコード

// 액티비티 코드
class MainActivity : AppCompatActivity() {
    // activity-ktx의 viewModels()  위임 사용
    // 액티비티의 scope안에서 ViewModel을 획득
    private val viewModel: ItemViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel.selectedItem.observe(this, Observer { item ->
            // 획득한 아이템에 대한 액션 지정
            Toast.makeText(this, "item : $item", Toast.LENGTH_SHORT).show()
        })
    }
}

// 프래그먼트 코드
class ListFragment : Fragment() {
    // fragment-ktx의 activityViewModels()를 사용하여 액티비티 scope의
    // ViewMoel 획득
    private val viewModel: ItemViewModel by activityViewModels()

    // 아이템이 클릭되면 호출
    fun onItemClicked(item: Item) {
        // ViewModel의 selectItem을 호출하여 MutableLiveData.setValue 호출
        viewModel.selectItem(item)
    }
}
  • 同じアクティビティ内のアイテム間でデータを共有する場合は、上記と同じアクティビティアイテムのViewModelを使用できます.親アイテム-子アイテムの関係でデータを共有する場合は、ViewModelの役割ドメインとして親アイテムを使用できます.
  • Fragment Result APIの使用


    Fragment Result APIは、スケジュール間またはホストアクティビティとスケジュール間で一時的な値を渡すために使用することができる.たとえば、QRコードを読み取り、以前の計画にデータを転送することができます.このAPIはFragment 1.3.0-alpha 04から追加された機能で、FragmentManagerはFragmentResultOwnerインタフェースを実装しています.


    FragmentResultOwnerは、計画間で渡されるデータを管理するクラスです.このインタフェースには、リスナーを登録してデータを受信する方法が含まれています.したがって、この機能を実装するFragmentManagerは、「ドラフト結果(データ)」の中央リポジトリとして機能します.

    依存項目の追加


    まずはAndroid KTXのFragment KTXを追加.Android KTXはCortlinの拡張機能をAndroid JetpackとAndroidライブラリに応用している.
    dependencies {
        implementation "androidx.fragment:fragment-ktx:1.4.0"
    }

    計画間でのデータの転送



    構造は以下の通りです.

  • 計画Bから計画Aにデータが転送されると仮定する.

  • 受信データの計画Aは、FragmentManagerでsetFragmentResultListener(「RequestKey」)メソッドを使用して、リスナーを所定のRequestKeyに設定します.

  • データを転送する計画Bは、setFragmentResult(「RequestKey」、Bundle)メソッドを使用して、所与のRequestKeyにデータを格納する.データは、FragmentManagerを介して同じリクエストキーでリスナーが登録されているプランAに送信されます.
  • コードを確認しましょう.
    まず、結果を受信する「ドラフトインフラストラクチャA」に結果リスナーを設定する.計画AのFragmentManagerでは、次の例のようにsetFragmentResultListener()が呼び出されます.

    データ受信計画

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // fragment-ktx의 코틀린 확장을 사용
        // 주어진 requestKey를 사용하여 FragmentResultListener를 설정
        setFragmentResultListener("requestKey") { requestKey, bundle ->
            // 데이터를 수신하고 생명주기 STARTED 상태가 되면 호출되는 콜백 메소드
            val result = bundle.getString("bundleKey")
            
            // Do something with the result
        }
    }
    データを転送する計画インフラストラクチャBは、RequestKeyを使用して同じFragmentManagerでデータを設定します.setFragmentResult()を使用してデータを設定できます.

    データ転送計画

    button.setOnClickListener {
        val result = "result"
        // Use the Kotlin extension in the fragment-ktx artifact
        // fragment-ktx의 코틀린 확장을 사용
        // setFragmentResult 메소드에 key와 Bundle을 사용해 데이터 전송
        setFragmentResult("requestKey", bundleOf("bundleKey" to result))
    }

    親と子の間でデータを渡す



    下位レベルのデータを下位レベルのデータに転送するには、setFragmentResultListener()ではなく、上位レベルの呼び出し時にgetParentFragmentManager()を使用します.

    データを受信する親計画

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // child Fragment Manager에 리스너 등록
        childFragmentManager.setFragmentResultListener("requestKey") { key, bundle ->
            val result = bundle.getString("bundleKey")
            // Do something with the result
        }
    }

    データ転送のサブプラン

    button.setOnClickListener {
        val result = "result"
        setFragmentResult("requestKey", bundleOf("bundleKey" to result))
    }

    ホストアクティビティからのデータの受信


    getSupportFragmentManager()を使用して、分割マネージャで結果リスナーを設定し、ホストアクティビティからタグからのデータを受信します.

    受信データのホストアクティビティ

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            supportFragmentManager
                    .setFragmentResultListener("requestKey", this) { requestKey, bundle ->
                // We use a String here, but any type that can be put in a Bundle is supported
                val result = bundle.getString("bundleKey")
                // Do something with the result
            }
        }
    }
    リファレンス
    Android Developer-クリップ付き通信
    分割領域間でデータを転送する方法
    Android-ViewModel
    Android-LiveDataとObserver
    Android-分割と分割マネージャ
    アンドロイド分割転送
    間違った部分にコメントを残したら修正します…!!