[1]. Fragment-Fragment 또는 Fragment-Host Activity 간 통신을 하기 위한 간단한 방법으로는
Jetpack 의 ViewModel 라이브러리와 LiveData 라이브러리를 사용하는 방법이다.
ViewModel 은 기기의 구성 변경이 발생하여 컴포넌트가 재생성 되더라도 컴포넌트의 상태를 유지하기 위한 용도로 사용되며 LiveData 는 컨트롤러(예: Activity) 에 데이터 변경 사실을 알려주는 용도로 사용된다.
[2]. ViewModel 객체를 생성하기 위해서 ViewModelProvider 클래스를 사용하는데 이때 ViewModelProvider 의 생성자에는 ViewModelStoreOwner 라는 값을 넘겨줘야 한다. 이미 생성된 ViewModel 객체를 가져오거나 새로운 ViewModel 객체를 생성할 때 생성자를 통해 전달받은 ViewModelStoreOwner 내의 ViewModelStore 에 접근하여 이미 생성된 ViewModel 객체를 가져오거나, 새로운 ViewModel 객체를 생성하여 저장한다. 그렇기 때문에 Fragment 또는 Host Activity 가 같은 ViewModel 객체를 참조하기 위해서는 동일한 ViewModelProvider 생성자에 동일한 ViewModelStoreOwner 를 전달하여서 ViewModel 객체를 가져와야 한다.
[3]. Fragment-Host Activity 간 통신
1. AFragment 에서 설정한 값을 MainActivity 에 알려주기 위해 AFragment 와 MainActivity 모두 ViewModel 을 생성할 때 ViewModelStoreOwner 를 Host Activity(MainActivity) 로 지정해준다.
2. MainActivity 에서 AFragment 로 부터 변경 사항을 통지받기 위해 ViewModel 객체 내의 LiveData 를 관찰한다.
3. AFragment 에서 ViewModel 내의 LiveData 에 값을 설정하는 순간 MainActivity 에서 등록한 LiveData 옵저버에도 통지가 가게되고 따라서 MainActivity 에서도 값이 변경되었음을 알아차릴 수 있게 된다.
MainActivity.kt
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater)}
private val viewModel: MainViewModel by lazy { ViewModelProvider(this).get(MainViewModel::class.java)}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
initViews()
initViewModel()
}
private fun initViews() {
binding.aFragmentButton.setOnClickListener {
supportFragmentManager.beginTransaction().apply {
replace(R.id.fragment_container_view, AFragment())
addToBackStack(null)
commitAllowingStateLoss()
}
}
}
private fun initViewModel() {
viewModel.item.observe(this) {
Log.d("Communication", "MainActivity::${it}")
}
}
}
AFragment.kt
class AFragment : Fragment() {
private var _binding: FragmentABinding? = null
private val binding get() = _binding!!
private val viewModel: MainViewModel by lazy { ViewModelProvider(requireActivity()).get(MainViewModel::class.java)}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
- }
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
-- _binding = FragmentABinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
initViewModel()
}
private fun initViews() {
binding.setItemButton.setOnClickListener {
viewModel.setItem("A Fragment 에서 set item 버튼을 클릭했습니다.")
}
}
private fun initViewModel() {
viewModel.item.observe(viewLifecycleOwner) {
Log.d("Communication", "AFragment::${it}")
}
}
}
MainViewModel.kt
class MainViewModel : ViewModel() {
private val _item: MutableLiveData<String> = MutableLiveData()
val item: LiveData<String> get() = _item
fun setItem(item: String) {
_item.value = item
}
}'android' 카테고리의 다른 글
| Firebase Ream-Time Database Paging 처리 (1) | 2022.10.25 |
|---|---|
| DialogFragment width 조정 (0) | 2022.10.22 |
| Fragment Transaction 동작 분석 (0) | 2022.10.10 |
| registerForActivityResult 메서드의 동작과정 (0) | 2022.02.03 |
| context (0) | 2022.01.20 |