[안드로이드 공식문서 파헤치기] RecyclerView의 모든 것! - 3편(RecyclerdViewPool)

dada·2022년 8월 5일
4
post-thumbnail

✅RecyclerdViewPool

  • RecyclerView의 모든 것! - 2편(ViewHolder수명주기)을 공부하면서 RecyclerdViewPool을 공유할 수 있다는 사실을 알게됐습니다! 공식문서를 보면 RecycleViewPool을 사용하면 여러 RecycleerView 간에 뷰를 공유할 수 있고,RecycleerViews 간에 뷰를 재활용하려면 RecycledViewPool 인스턴스를 만들고 setRecycledViewPool(재활용ViewPool)을 사용하면 된다고 나와있다.

  • 즉 여러 RecyclerView들이 동일한ViewHolder를 사용한다면 Pool을 공유해서 ViewHolder를 함께 재사용하기 때문에 불필요한 ViewHolder생성을 줄이고 성능을 최적화할 수 있다.

class Example2Fragment : BaseViewUtil.BaseFragment<FragmentExample2Binding>(com.ummaaack.myapplication.R.layout.fragment_example2) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
       binding.rv.adapter=RecyclerView2Adapter()
        binding.rv.layoutManager=LinearLayoutManager(requireContext())
    }
}

class Example3Fragment : BaseViewUtil.BaseFragment<FragmentExample3Binding>(com.ummaaack.myapplication.R.layout.fragment_example3) {
 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
     
        binding.rv.adapter = RecyclerView2Adapter()
        binding.rv.layoutManager = LinearLayoutManager(requireContext())
    }
}
  • 하나의 Activity에 두개의 Fragment가 host되어있는 모습입니다. 각 Example2Fragment, Example3Fragment는 RecyclerView를 가지고 있고 RecyclerView2Adapter라는 어댑터를 사용합니다

  • 이때 같은 RecyclerView2Adapter class를 사용하고 viewType도 하나이기때문에 두 RecyclerView는 같은 ViewHolder를 사용하고 있습니다. 하지만 Adapter는 각자의 ViewHolder를 만들어 재활용합니다.

  • 즉 동일한 ViewHolder를 사용하지만 RecycledViewPool을 공유하지 않기때문에 불필요한 onCreateViewHolder가 생성되는 것입니다

  • Example2Fragment, Example3Fragment의 Adapter가 거의 동시에 생성되어 Fragment에 붙은 후 onAttacedToRecyclerView가 호출되어 RecyclerView가 화면에 나타납니다. 그 후 초록색 부분(Example2Fragment)의 Fragment가 호스팅되어 ViewHolder를 생성하고 뒤이어 파란색 부분(Example3Fragment)의 Fragment가 호스팅되어 ViewHolder를 생성합니다
  • 이후 초록색(Example2Fragment) Fragment의 스크롤을 내리면 ViewHolder가 생성되다가 onViewRecycled가 호출되며 ViewHolder가 재활용됩니다. 이때 파란색(Example3Fragment) 프래그먼트의 스크롤을 내리면 Example2Fragment의 Adapter와 RecycledViewPool을 공유하지 않기 때문에 같은 viewType의 ViewHolder임에도 뷰홀더를 재활용하지 않고(onViewRecycled호출안됨) 새로운 onCreatedViewHolder를 호출함을 알 수 있습니다

✅RecyclerdViewPool 공유하는 법

  • RecyclerView의 내부 class인 RecycledViewPool의 객체를 생성하여 RecyclerView들이 공유할 수 있는 pool을 생성합니다

  • 이후 RecyclerView가 가진 메서드인 setRecycledViewPool()의 파라미터로 생성했던 RecycledViewPool객체를 전달합니다

class PoolRvActivity : AppCompatActivity() {
    val sharedPool = RecyclerView.RecycledViewPool() //pool생성
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_rv)

        val sharedPool = RecyclerView.RecycledViewPool()
    }
    
    fun getPool():RecyclerView.RecycledViewPool{
        return sharedPool
    }
}
  • Fragment들이 host되어있는 PoolRvActivity 에서 getPool()을 선언하여 RecycledViewPool을 전달하도록 했습니다
class Example2Fragment : BaseViewUtil.BaseFragment<FragmentExample2Binding>(com.ummaaack.myapplication.R.layout.fragment_example2) {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
   
   binding.rv.adapter = RecyclerView2Adapter(binding.rv) //어댑터 설정
        binding.rv.layoutManager = LinearLayoutManager(requireContext())
        val activity = requireActivity() as PoolRvActivity
        binding.rv.setRecycledViewPool(activity.getPool())
   
        (binding.rv.layoutManager as LinearLayoutManager).recycleChildrenOnDetach = true //
    }
}
  • 각 Fragment에서는 메서드로 getPool()의 리턴값인 sharedPool을 전달받아 setRecycledViewPool의 파라미터로 전달합니다.
    `

  • bind될 때마다 pool의 참조값을 로그로 확인해봤더니, 두 adapter가 같은 Pool을 사용하고 있음을 알 수 있었습니다

  • 또한 onCreateViewHolder 호출 회수가 줄어들어든걸 확인했습니다!

profile
'왜?'라는 물음을 해결하며 마지막 개념까지 공부합니다✍

0개의 댓글