ActivityとFragmentの通信

2022-02-23
AndroidKotlin

はじめに

Androidデベロッパーのフラグメントと通信するのほうが詳しいです。

activityViewModels

ActivityScopeにあるViewModelを使うのがわかりやすい気がします。

class HomeFragment: Fragment(R.layout.fragment_home) {
private val mainViewModel: MainViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainViewModel.textLiveData.observe(viewLifecycleOwner){
Log.d("HomeFragment","MainActivityのViewModelが使える!")
}
mainViewModel.sendValue("こっちから送ることもできる")
}
}
class MainActivity : AppCompatActivity(R.layout.activity_main) {
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportFragmentManager.commit {
replace(R.id.fragment,HomeFragment())
}
viewModel.textLiveData.observe(this) {
Log.d("MainActivity", it)
}
}
}
class MainViewModel: ViewModel() {
private val mutableTextLiveData = MutableLiveData<String>()
val textLiveData: LiveData<String> = mutableTextLiveData
fun sendValue(value: String) {
mutableTextLiveData.value = value
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

ログの出力はこんな感じでActivityとFragmentが同じViewModelを使用しているのがわかると思います。

D/HomeFragment: MainActivityのViewModelが使える!
D/MainActivity: こっちから送ることもできる

これはいくつFragmentを増やしても同じViewModelを使用するため、
Fragment同士の通信にも利用できます。

Fragment Result

Fragment Result APIを使用する方法もあります。
ただ、ViewModelに比べて少し複雑です。

class HomeFragment: Fragment(R.layout.fragment_home) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val result = "親(Activity)に値を送れます。"
setFragmentResult(REQUEST_KEY, bundleOf(BUNDLE_KEY to result))
}
override fun onResume() {
super.onResume()
val result = "二回目以降もできないことはないです。"
setFragmentResult(REQUEST_KEY, bundleOf(BUNDLE_KEY to result))
}
companion object {
const val REQUEST_KEY = "requestKey"
const val BUNDLE_KEY = "bundleKey"
}
}
class MainActivity : AppCompatActivity(R.layout.activity_main) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportFragmentManager.commit {
replace(R.id.fragment,HomeFragment())
}
supportFragmentManager
.setFragmentResultListener(
HomeFragment.REQUEST_KEY,
this
) { requestKey, bundle ->
val result = bundle.getString(HomeFragment.BUNDLE_KEY)
Log.d("MainActivity", result.orEmpty())
}
}
}
D/MainActivity: 親(Activity)に値を送れます。
D/MainActivity: 二回目以降もできないことはないです。
© 2022 シロボタン - Context Composition