개요
아래와 같은 기존 코드의 경우 뷰가 완전히 생성된 이후 네트워킹 작업을 수행한 뒤 뷰를 갱신하여 UX가 좋지 않았다.
내가 원하는 방향은 네트워킹을 통해 데이터를 전부 가져오고 이 작업이 마무리되고 뷰가 갱신되는 것을 원했다.
class BoardFragment : Fragment() {
lateinit var repository: Repository
lateinit var adapter: PostPageAdapter
private val mDisposable = CompositeDisposable()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
adapter = PostPageAdapter(requireContext()) {
val directions = BoardFragmentDirections.actionCommunityFragmentToPostFragment(it.id!!)
findNavController().navigate(directions)
(requireActivity() as MainActivity).main_bottom_navigation.visibility=View.GONE
}
repository = Repository(activity!!.application)
return inflater.inflate(R.layout.fragment_board, container, false)
}
override fun onResume() {
super.onResume()
(requireActivity() as MainActivity).main_bottom_navigation.visibility=View.VISIBLE
adapter.notifyDataSetChanged()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recycler_view.setItemViewCacheSize(20)
...
val pagedItems = builder.buildObservable()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe({
(recycler_view.adapter as PostPageAdapter).submitList(it)
}, {
it.stackTrace
})
mDisposable.add(pagedItems)
recycler_view.adapter = adapter
}
...
}
액티비티와 프래그먼트의 생명주기
아래는 액티비티와 프래그먼트의 생명주기를 연관지어 보여준 흐름도이다. 현재 포스팅에서 주목할 부분은 프래그먼트 생명주기의 onCreate(), onCreateView()이다.
onCreate()
해당 콜백은 프래그먼트가 생성될 때 단 한번만 호출된다. 따라서, 이 콜백에서는 데이터와 같은 리소스 초기화 작업을 수행하는게 적합하다.
onCreateView()
해당 콜백은 뷰가 생성되어 매개변수로 사용가능한 시점이다. 또한, 프래그먼트가 백스택에서 되돌아오는 지점이기도 하다.
onViewCreated()
해당 콜백은 onCreateView()가 호출된 직후 호출된다. 뷰가 완전히 생성되어 있는 지점이다.
리팩토링
아래는 위의 개념을 알고난 뒤 리팩토링한 코드이다.
onCreate에서는 adapter,repository를 초기화하고 네트워킹을 통해 데이터를 가져온다.
onCreateView에서는 view에 대한 초기화 작업을 수행한다.
onViewCreated에서는 리사이클러뷰에 실제 어답터를 붙여 데이터를 보여준다.
class BoardFragment : Fragment() {
lateinit var repository: Repository
lateinit var adapter: PostPageAdapter
private val mDisposable = CompositeDisposable()
private lateinit var pagedItems: Disposable
override fun onAttach(context: Context) {
super.onAttach(context)
Util.progressOnInFragment(this)
}
//Callback when fragment is created
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
adapter = PostPageAdapter(requireContext()) {
val directions = BoardFragmentDirections.actionCommunityFragmentToPostFragment(it.id!!)
findNavController().navigate(directions)
(requireActivity() as MainActivity).main_bottom_navigation.visibility=View.GONE
}
repository = Repository(activity!!.application)
initData()
}
//Callback first init & return from back stack
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_board, container, false)
(requireActivity() as MainActivity).main_bottom_navigation.visibility=View.VISIBLE
view.write_post_btn.setOnClickListener { goToWritePostFragment() }
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recycler_view.setItemViewCacheSize(20)
recycler_view.adapter = adapter
}
private fun initData(){
val config= PagedList.Config.Builder()
.setPageSize(20) //Defines the number of items loaded at once from the DataSource.
.setInitialLoadSizeHint(20) //Defines how many items to load when first load occurs. Default = PAGE SIZE * 3
.setPrefetchDistance(20) //Defines how far from the edge of loaded content an access must be to trigger further loading.
.setEnablePlaceholders(true) //Pass false to disable null placeholders in PagedLists using this Config.
.build()
val builder = RxPagedListBuilder<Int, Post>(PostDataSourceFactory(repository,mDisposable), config)
pagedItems = builder.buildObservable()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe({
adapter.submitList(it)
Util.progressOffInFragment()
}, {
it.stackTrace
})
mDisposable.add(pagedItems)
}
...
}
Note
안드로이드 개발을 하면 할수록 많은 문제는 생명주기와 연관이 있는 것 같다. 이에 대한 꾸준한 학습이 필요해 보인다.
'안드로이드 > 안드로이드 디버깅' 카테고리의 다른 글
[디버깅] 게시판에서 특정 게시글을 보고 다시 게시판으로 돌아올 때 보던 위치로 돌아오기 (0) | 2021.01.08 |
---|---|
[디버깅] 맵뷰 위에 다른 레이아웃 그리기 (0) | 2021.01.07 |
[디버깅] SwipeRefreshLayout+RecyclerView 조합에서 item click 이벤트 수신 불가 문제 (0) | 2020.11.29 |
[디버깅] 리사이클러뷰 스크롤 다운 시 아이템이 뒤섞이는 문제 (0) | 2020.11.29 |
[디버깅] 리사이클러뷰 아이템이 제대로 나오지 않는 문제 (0) | 2020.11.06 |