이번 프로젝트에서 Activity 툴바의 버튼을 누르면 tabLayout 과 연결된 viewPager 의 fragment에 있는 캐릭터를 흑백/컬러로 변경하는 작업을 했습니다.
처음에 구현하기 전에는 그냥 인터페이스로 통신하면 되지 않을까?
하는 생각을 했었는데요....
그랬다면 이 포스트를 쓰고 있지 않았을 겁니다ㅋㅋ 생각보다 어렵더군요
왜냐하면 viewPager 로 fragment 를 초기화할 때, 다시 초기화 시키는 방법을 선택하면
화면이 지워졌다가 깜빡하면서 다시 그려지는데 이것은 우리가 원하던 디자인이 아니기 때문입니다.
따라서 화면을 다시 그리지 않으면서 fragment 의 recyclerview 의 item 만 바꾸는 방법이 무엇일지 고민해야 했습니다.
열심히 구글링한 결과, 재미있는 사실을 알게 되었습니다.
//GroupActivity.kt
override fun onPatchSingleStatusSuccess() {
if(changeToSingle) binding.customToolbar.rightIcon.setImageResource(R.drawable.ic_icons)
else binding.customToolbar.rightIcon.setImageResource(R.drawable.ic_icon)
viewPagerAdapter.notifyDataSetChanged()
}
먼저 viewPagerAdatper의 notifyDataSetChanged 를 콜합니다.
그러면 바뀐 데이터를 bind 시키기 위해서 FragmentStateAdapter 의 onBindViewHolder 가 호출됩니다.
//viewpagerAdapter.kt
private const val GROUP_TAB_NUM = 4
class GroupViewPagerAdapter(
fm: FragmentActivity,
private val groupActivity: GroupActivity
) : FragmentStateAdapter(fm) {
var fragmentList = arrayListOf<Fragment>(GroupMainFragment(), GroupCategoryFragment(), GroupVoteFragment(), GroupMemberFragment())
override fun getItemCount(): Int = GROUP_TAB_NUM
override fun createFragment(position: Int): Fragment {
return fragmentList[position]
}
override fun onBindViewHolder(
holder: FragmentViewHolder,
position: Int,
payloads: MutableList<Any>
) {
super.onBindViewHolder(holder, position, payloads)
val fragment: GroupMemberFragment? = groupActivity.supportFragmentManager.findFragmentByTag("f$position") as? GroupMemberFragment?
fragment?.reload()
}
}
onBindViewHolder 안에서 찾고자 하는 fragment 를 찾습니다.
//GroupMemberFragment.kt
private fun getGroupMember() {
showLoadingDialog(requireContext())
GroupMemberService(this).tryGetGroupMember(getUserIdx(), getGroupIdx())
}
fun reload() {
getGroupMember()
}
override fun onGetGroupMemberSuccess(response: GroupMemberResponse) {
dismissLoadingDialog()
val memberList: MutableList<GroupMember> =
response.result.members as MutableList<GroupMember>
memberList.add(
GroupMember(
userIdx = -10,
color = 0,
characters = 0,
nickName = " ",
singleStatus = " "
)
)
memberAdapter = MemberRVAdapter(requireContext(), memberList.toList(), this)
binding.rvMember.apply {
adapter = memberAdapter
layoutManager = GridLayoutManager(requireContext(), 4)
clipToPadding = false
}
}
해당 fragment 에서 recyclerView 를 다시 로드합니다.
코드는 장황했지만.. ㅎ 사실 이번 포스트의 핵심은 이것입니다!
val fragment: GroupMemberFragment? = groupActivity.supportFragmentManager.findFragmentByTag("f$position") as? GroupMemberFragment?
FragmentStateAdapter 에서 원하는 fragment 에 접근하는 방법!
findFragmentByTag 로 찾고 해당 fragment 의 public method 로 통신하면 됩니다!