원하는 동작 : ImageListFragment에서 RecyclerView의 이미지 리스트 중 하나를 클릭하면
클릭한 이미지의 Position을 받아와 GalleryFragment에서 ViewPager 형태로 해당 이미지를 보여준다.
ViewPager2의 current position을 이미지의 position으로 설정한다.
발생한 문제 : current position 설정과 관계 없이 리스트의 첫번째 이미지가 보여진다.
기존 코드 :
// RecyclerViewBinding.kt
@JvmStatic
@BindingAdapter("submitListViewPager")
fun bindSubmitListViewPager(view: ViewPager2, list: Array<RedditImage>) {
(view.adapter as GalleryPagerAdapter).apply {
images = list
notifyDataSetChanged()
}
}
// fragment_gallery.xml
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
app:submitListViewPager="@{images}"
android:background="@color/black"
android:layout_width="match_parent"
android:layout_height="match_parent" />
BindingAdapter를 통해 viewPager의 아이템 리스트를 업데이트한다.
// GalleryFragment
private fun initViews() = with(binding) {
viewPager.adapter = pagerAdapter
images = args.images
val position = args.position
viewPager.setCurrentItem(position, false)
}
GalleryFragment의 onCreateView 메소드에서 view에 대한 초기화를 수행하는 해당 메소드를 실행한다.
이 때 setCurrentItem이 동작하지 않는 이유는 각 line의 실행 타이밍에 있다.
제대로 setCurrentItem이 동작하려면 다음과 같은 순서가 보장되어야 한다.
1. images = args.images를 통해 BindingAdapter에서 ViewPager에 image list가 전달되고 리스트가 뷰페이저와 바인딩 된다.
2. ViewPager의 setCurrentItem 메소드가 동작하여 바인딩 된 image list를 기반으로 position이 설정된다.
뷰페이저에 바인딩 된 image list를 기반으로 setCurrentItem 메소드가 동작해야한다.
하지만 Log를 통해 순서를 확인해보니 다음과 같았다.
데이터 바인딩의 submitList 동작보다 setCurrentItem 메소드의 동작이 우선적으로 이루어진다.
그러므로 비어있는 뷰페이저의 리스트에 position이 설정된 뒤 submitList가 동작하여 뒤늦게 리스트가 새로 바인딩 됨으로써 기존에 설정한 current position이 초기화된다.
해결 코드 :
ViewPager에 리스트가 바인딩 된 뒤에 setCurrentItem 메소드가 수행 될 수 있도록 position까지 BindingAdapter에 넘겨주고 BindingAdapter에서 setCurrentItem 메소드를 수행 할 수 있도록 하였다.
@JvmStatic
@BindingAdapter("submitListViewPager", "currentPosition")
fun bindSubmitListViewPager(view: ViewPager2, list: Array<RedditImage>, position: Int) {
(view.adapter as GalleryPagerAdapter).apply {
images = list
notifyDataSetChanged()
} // submitList
view.setCurrentItem(position, false) //set current Item
}
BindingAdapter 메소드에 submitList, setCurrentItem 동작을 동기적으로 처리하여 submitList -> setCurrentItem 순서가 보장되었다. 드디어 정상 동작한다.
소스코드 : https://github.com/HunSeongPark/gallerit-clone
'Android' 카테고리의 다른 글
[Android, Kotlin] Room DB에서 Flow를 사용하여 DB 변경 observing (6) | 2021.12.07 |
---|---|
[Android, Kotlin] Coroutine Flow block 내에서 여러 개의 suspend function에 대한 비동기 처리 (2) | 2021.12.06 |
[Android, Kotlin] Hilt에서 @Binds와 @Provides의 차이점 (6) | 2021.11.25 |
[Android] Exception 종류와 내용 (2) | 2021.11.20 |
[Android, Kotlin] 멀티 스레드 간 통신을 위한 Handler, Looper (2) | 2021.11.20 |