[안드로이드] Activity->ViewPager (FragmentStateAdapter) Fragment 통신

에짱·2021년 9월 5일
0
post-custom-banner

이번 프로젝트에서 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 로 통신하면 됩니다!

profile
지금 여기. Here and Now
post-custom-banner

0개의 댓글