๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿค2024 ์•ˆ๋“œ๋กœ์ด๋“œ/๐Ÿฟ ์˜ํ™” ํ”„๋กœ์ ํŠธ ๊ฐœ๋ฐœ ์ผ์ง€

๐Ÿ™Œ๋ฌดํ•œ ์Šคํฌ๋กค ์†์ˆ˜ ๊ตฌํ˜„ํ•ด๋ณด๋‹ค.

by hyeonha 2024. 10. 12.

๋ชฉ์ฐจ

    ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—

    ์˜ํ™”๋ฅผ ๊ฒ€์ƒ‰ํ•œ ํ›„ ์˜ํ™” ํฌ์Šคํ„ฐ๋“ค์„ ํ™”๋ฉด์— ๋„์šธ ๋•Œ "๋ฌดํ•œ ์Šคํฌ๋กค " ์„ ๊ตฌํ˜„ํ•ด์•ผํ–ˆ๋‹ค.

    ๋ฌดํ•œ ์Šคํฌ๋กค์„ ์†์ˆ˜ ๊ตฌํ˜„ํ•˜๋ฉด ๊ฒช์€ ๋‚ด์šฉ์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด๋ณด๋ คํ•œ๋‹ค.

     

    ๋ฌดํ•œ ์Šคํฌ๋กค์˜ ๋‚ด์šฉ์„ ๋จผ์ € ์ •๋ฆฌํ•ด๋ณด์ž 

    ๋ฌดํ•œ ์Šคํฌ๋กค์ด๋ž€?

    ๋ฌดํ•œ ์Šคํฌ๋กค์ด๋ž€ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ๋ฒˆ์— ๋กœ๋“œํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์‚ฌ์šฉ์ž๊ฐ€ ์•„๋ž˜๋กœ ์Šคํฌ๋กคํ•  ๋•Œ ์ฝ˜ํ…์ธ ๊ฐ€ ๋™์ ์œผ๋กœ ๋กœ๋“œ๋˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

    ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ๋ฒˆ์— ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋กœ๋”ฉ ์‹œ๊ฐ„์ด ์ค„์–ด๋“ ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค!

    ๊ฒ€์ƒ‰์–ด์— ๋”ฐ๋ผ์„œ ํ•ด๋‹นํ•˜๋Š” ์˜ํ™” ๋ชฉ๋ก์„ page๋ณ„๋กœ ๊ฐ€์ ธ์˜ค๋„๋ก ์„ค๊ณ„๋œ ์„œ๋ฒ„ api๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด page๋ฅผ ์ด์šฉํ•œ ๋ฌดํ•œ ์Šคํฌ๋กค์„ ๊ตฌํ˜„ํ•ด๋ณด์•˜๋‹ค.

     

    ๋ฐ”๋กœ ๊ฒฐ๊ณผ๋ถ€ํ„ฐ ๋ณด์žฅ

    ๊ตฌํ˜„๋œ ๋ฌดํ•œ ์Šคํฌ๋กค์ด๋‹ค !! 

     

    ๋ฌดํ•œ ์Šคํฌ๋กค ํŒ๋‹จ

    ์•„๋ž˜ ๋กœ์ง์— ๋”ฐ๋ผ ์Šคํฌ๋กค์ด ์ตœํ•˜๋‹จ์— ๋„๋‹ฌํ–ˆ์Œ์„ ํŒ๋‹จํ•ด์„œ ๋‹ค์Œ ํŽ˜์ด์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™”๋‹ค.

    ๋กœ๋”ฉ์ด ๋˜๊ณ  ์žˆ๋Š”๊ฑด๊ฐ€?! 

    ๊ทธ๋Ÿฐ๋ฐ ํŽ˜์ด์ง€๊ฐ€ ๋„˜์–ด๊ฐˆ ๋•Œ๋งˆ๋‹ค ๋กœ๋”ฉ์ด ๋˜๊ณ  ์žˆ์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์ข‹๊ฒ ๋‹ค. 

    ๊ทธ๋ ‡๊ฒŒ ... ๋กœ๋”ฉ ๋ ˆ์ด์•„์›ƒ์— ์ถ”๊ฐ€ํ•ด์ฃผ๋ ค๊ณ  ํ–ˆ๋Š”๋ฐ ... ์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ๋‹ค.!!

    ๋ฌธ์ œ ๋ฐœ์ƒ

     

    ๊ทธ๋ฆฌ๋“œ๋ทฐ๋ฅผ ํ†ตํ•ด ์˜ํ™” ํฌ์Šคํ„ฐ๊ฐ€ ๋œจ๋‹ค๊ฐ€ ๋‹ค์Œ ํŽ˜์ด์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ๊นŒ์ง€ ๋กœ๋”ฉ์„ ํ‘œ์‹œํ•˜๊ณ ์ž ํ–ˆ๋‹ค.

    ์ฒซ ๋ฒˆ์งธ ์‹œ๋„ :  ๋‹จ์ˆœํžˆ ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์— Lottie์˜ ๋กœ๋”ฉ ์ด๋ฏธ์ง€๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค.

     

    ๊ฒฐ๊ณผ๋Š” ์•„๋ž˜์™€ ๊ฐ™์•˜๋‹ค...

     

     

    ๋กœ๋”ฉ์ด ์žˆ๋Š”์ง€๋„ ํ™•์ธํ•˜๊ธฐ ์–ด๋ ค์› ๊ณ  ์ œ๋Œ€๋กœ ๊ตฌํ˜„๋˜์ง€ ์•Š์•˜๋‹ค.

    ๋‘ ๋ฒˆ์งธ ์‹œ๋„๋Š” BaseAdapter๋ฅผ ์ƒ์†๋ฐ›์€ ํด๋ž˜์Šค์—์„œ ์—ฌ๋Ÿฌ ๋ทฐ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

     

    ๋กœ๋”ฉ ์—ฌ๋ถ€ ์ •๋ณด๋ฅผ ํ”„๋ž˜๊ทธ๋จผํŠธ์—์„œ ์–ด๋Œ‘ํ„ฐ๋กœ ์ „๋‹ฌํ•ด์ฃผ๊ณ  ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋ทฐ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๋ฐฉ์‹์œผ๋กœ ์‹œ๋„ํ•ด๋ณด์•˜๋‹ค.

    ๋งˆ์ง€๋ง‰์œผ๋กœ ์–ด๋Œ‘ํ„ฐ์—์„œ ๋กœ๋”ฉ ์—ฌ๋ถ€ ์ •๋ณด๋ฅผ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•ด์ฃผ๊ณ  ํ•ด๋‹น ๊ฐ’์— ๋”ฐ๋ผ์„œ ๋ทฐ๋ฅผ ๋‹ฌ๋ฆฌํ•ด์ฃผ์—ˆ๋‹ค.

     

    ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋ณด์ž.

    ์ตœํ•˜๋‹จ์ด๋ผ๋ฉด ๋กœ๋”ฉ์„ true๋กœ ์„ค์ •ํ•ด์ฃผ๊ณ , page๋ฅผ 1๋งŒํผ ์ฆ๊ฐ€์‹œํ‚ค ํ›„ ๋‹ค์Œ ๋ฐ์ดํ„ฐ๋ฅผ ํ˜ธ์ถœํ•ด์ฃผ์—ˆ๋‹ค.

     binding.movieGridView.setOnScrollListener(
                object : AbsListView.OnScrollListener {
                    private var isLoading = false
    
                    override fun onScrollStateChanged(
                        view: AbsListView?,
                        scrollState: Int,
                    ) {
                    }
    
                    override fun onScroll(
                        view: AbsListView?,
                        firstVisibleItem: Int,
                        visibleItemCount: Int,
                        totalItemCount: Int,
                    ) {
                    // !๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ.canScrollVertically(1) : ๊ทธ๋ฆฌ๋“œ๋ทฐ๊ฐ€ ์ตœํ•˜๋‹จ์— ๋‹ฟ์€ ๊ฒƒ 
                    // ์ด๋ฅผ ํ†ตํ•ด ์ตœํ•˜๋‹จ์— ๋‹ฟ์•˜๊ณ  ๋กœ๋”ฉ์ด ์•„๋‹ˆ๋ผ๋ฉด ๋กœ๋”ฉ์ค‘์œผ๋กœ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ด์ฃผ๊ณ  
                    // ํŽ˜์ด์ง€๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚จ ํ›„ ๋ทฐ๋ชจ๋ธ์„ ํ†ตํ•ด ๋‹ค์Œ ํŽ˜์ด์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋„๋ก ํ•˜์˜€๋‹ค.
                        if (!binding.movieGridView.canScrollVertically(1) && !isLoading) {
                            isLoading = true
                            currentPage++
                            viewModel.handleEvent(MovieSelectEvent.LoadNextPageMovie(queryText, currentPage))
                        } else {
                            isLoading = false
                        }
                    }

     

    ๊ทธ๋ฆฌ๊ณ StateFlow๋ณ€์ˆ˜ moviePosterUriList๊ฐ€  ๋‹ค์Œ ํŽ˜์ด์ง€๋ฅผ ๊ฐ€์ ธ์™€์„œ ์ƒˆ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋˜๊ณ 

    ์ด ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋Œ‘ํ„ฐ์— ๋„˜๊ฒจ์ฃผ์—ˆ๋‹ค.

                   lifecycleScope.launch {
                        repeatOnLifecycle(Lifecycle.State.STARTED) {
                            viewModel.moviePosterUriList.collect {
                                moviePosterAdapter?.initializePosterUriList()
                                moviePosterAdapter?.setPosterUriList(it)

     

    ๊ทธ ๊ฒฐ๊ณผ ... ! ์˜ํ™” ํฌ์Šคํ„ฐ๋ฅผ ๋ฌดํ•œ ์Šคํฌ๋กค๋กœ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ๋Š” ์„ฑ๊ณตํ•˜์˜€์ง€๋งŒ ๋กœ๋”ฉ์„ ํ‘œ์‹œํ•˜๋Š”๋ฐ์—๋Š” ์‹คํŒจํ–ˆ๋‹ค.

    ๋กœ๋”ฉ ํ™”๋ฉด ์ถ”๊ฐ€ (๊ทธ๋ฆฌ๋“œ๋ทฐ์—์„œ ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ๋กœ ๊ต์ฒด!?)

    ์ง€๊ธˆ๊นŒ์ง€ GridView์™€ ๊ธฐ๋ณธ ๋ฒ ์ด์Šค์–ด๋Œ‘ํ„ฐ๋กœ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ๋กœ ์˜ํ™” ํฌ์Šคํ„ฐ๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ  ์žˆ์—ˆ๋Š”๋ฐ ์•„๋ฌด๋ฆฌ ํ•ด๋ณด์•„๋„  ๋ฐ์ดํ„ฐ + ๋กœ๋”ฉ ์„ ํ•จ๊ป˜ ํ‘œ์‹œํ•˜๊ธฐ ์–ด๋ ค์› ๋‹ค.

    ๐Ÿ˜ฑ ๋กœ๋”ฉ์ง€์˜ฅ์— ๋น ์ง€๊ธฐ๋„ ํ–ˆ๋‹ค ..

     

    ๋”ฐ๋ผ์„œ ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ๋ฅผ ํ†ตํ•ด ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ทฐ๋ฅผ ๋ณด์—ฌ์ฃผ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด ๋ณ€๊ฒฝํ•ด์ฃผ์—ˆ๋‹ค. ๋ฉ€ํ‹ฐ๋ทฐ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•ด๋ณธ ๊ฒฝํ—˜์ด ์žˆ์–ด์„œ ์ด๊ฑธ๋กœ ๊ตฌํ˜„ํ•ด๋ณด๋ฉด ๋˜๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด ๋ฐ”๋กœ ๋ณ€๊ฒฝํ•ด๋ณด์•˜๋‹ค!!

     

     

    // ๊ธฐ์กด 
    class MoviePosterAdapter(private val context: Context) : BaseAdapter()
    
    // ๋ณ€๊ฒฝ
    class MoviePosterAdapter(private val context: Context) : RecyclerView.Adapter<RecyclerView.ViewHolder>()
    	
        // ๋กœ๋”ฉ ์ƒํƒœ ๋ณ€์ˆ˜ 
        private var isLoading = false
        companion object {
            const val VIEW_TYPE_ITEM = 0
            const val VIEW_TYPE_LOADING = 1
        }
        
        // ๋กœ๋”ฉ ์ƒํƒœ ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•œ ๋ฉ”์„œ๋“œ
        fun setLoading(isLoading: Boolean) {
            this.isLoading = isLoading
        }
        
        // ๋ทฐ ํƒ€์ž…์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ ˆ์ด์•„์›ƒ๊ณผ ๋ทฐํ™€๋”๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ฃผ์—ˆ๋‹ค.
        override fun onCreateViewHolder(
            parent: ViewGroup,
            viewType: Int,
        ): RecyclerView.ViewHolder {
            return when (viewType) {
                VIEW_TYPE_ITEM -> {
                    val binding = MoviePosterItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                    MoviePosterViewHolder(binding)
                }
                VIEW_TYPE_LOADING -> {
                    val binding = ItemLoadingBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                    MovieLoadingViewHolder(binding)
                }

     

    โœจ์•ˆ๋“œ๋กœ์ด๋“œ ๊ฐœ๋ฐœ์ž ์งˆ๋ฌธ๋ฐฉ์„ ํ†ตํ•ด ์–ป์€ ์†Œ์ค‘ํ•œ ๋‹ต๋ณ€๋“ค 

     

    ์•ˆ๋“œ๋กœ์ด๋“œ ๊ฐœ๋ฐœ์ž ์งˆ๋ฌธ๋ฐฉ์„ ํ†ตํ•ด ์งˆ๋ฌธ์„ ํ•œ ๊ฒฐ๊ณผ ์•„๋ž˜ 2๊ฐ€์ง€๋ฅผ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

    1 . ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ์— footer & header๋ผ๋Š” ๊ฐœ๋…๊ณผ

    2. span ์ฒ˜๋ฆฌ ๋ฐฉ์‹์— ๋Œ€ํ•ด ์•Œ๊ฒŒ๋˜์—ˆ๋‹ค.

    ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ์˜ footer

    ๋จผ์ € ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ์˜ footer์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณธ ๊ฒฐ๊ณผ, ์–ด๋Œ‘ํ„ฐ๋ฅผ ์กฐ์ •ํ•ด์„œ ๋ฐ”๋‹ฅ๊ธ€์„ ์ถ”๊ฐ€ํ•ด์ฃผ๋Š” ๊ฐœ๋…์ด์—ˆ๋‹ค. 

    ๋‚ด์šฉ์„ ๋ณด๊ธฐ ์ „์—๋Š” footer๋ผ๋Š” ๊ฐœ๋…์ด ๋”ฐ๋กœ ์กด์žฌํ•˜๋Š” ๊ฑฐ๋ผ๊ณ  ์ƒ๊ฐํ•˜์˜€๋Š”๋ฐ ๋ฉ€ํ‹ฐ๋ทฐ๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•ด์ฃผ๋Š” ๋ฐฉ์‹์ž„์„ ์•Œ๊ฒŒ๋˜์—ˆ๋‹ค.

     

    ํฌ๊ฒŒ ์•„๋ž˜์˜ ํ๋ฆ„๋Œ€๋กœ ๊ตฌํ˜„ํ•ด์ฃผ๋ฉด ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ์ด๋ฏธ ์ ์šฉํ•ด์ฃผ๊ณ  ์žˆ๋˜ ๋ฐฉ์‹์ด์—ˆ๋‹ค!!

       // footer ์‹๋ณ„์„ ์œ„ํ•œ ๋ณ€์ˆ˜ ์„ ์–ธ
       private val TYPE_FOOTER = 2
       
     
     	// ์„œ๋กœ ๋‹ค๋ฅธ ๋ทฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ฃผ๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜์ด๋‹ค.
    override fun getItemViewType(position: Int): Int {
            return when {
                isFooter(position) -> TYPE_FOOTER
                else -> TYPE_ITEM
            }
        }
    
        // footer์™€ item์„ ์œ„ํ•œ ๋ทฐํ™€๋”๋ฅผ ์ƒ์„ฑํ•ด์ค€๋‹ค.
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            return when (viewType) {
                TYPE_FOOTER -> FooterViewHolder(footerView!!)
                else -> ItemViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false))
            }
       
         // ๋ทฐํ™€๋”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”์ธ๋”ฉํ•ด์ค€๋‹ค.
        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            when (holder) {
                is ItemViewHolder -> {
                    val itemData = data[getRealPosition(position)]  // Adjust position to account for header
                    holder.bind(itemData)
                }
            }
        }
        
        // footer๋ฅผ ์œ„ํ•œ ๋ทฐํ™€๋”๋ฅผ ๊ตฌํ˜„ํ•ด์ค€๋‹ค.
            class FooterViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

    span ์กฐ์ • ๋ฐฉ์‹

    ๋‹ค์Œ์€ span์„ ์กฐ์ •ํ•ด์ฃผ๋Š” ๋ฐฉ์‹์ด๋‹ค.

    ์ด ๋ฐฉ์‹์€ ์ฒ˜์Œ ์•Œ๊ฒŒ๋˜์–ด์„œ ์‹ ๊ธฐํ–ˆ๋‹คใ…Žใ…Ž 

    GridLayoutManager.SpanSizeLookup :๊ฐ ์•„์ดํ…œ์ด ์ฐจ์ง€ํ•  ํ–‰์˜ ์ˆ˜๋ฅผ ์ œ๊ณตํ•ด์ฃผ๋Š” ์—ญํ•  ์„ ํ†ตํ•ด ์ฐจ์ง€ํ•˜๊ณ  ์‹ถ์€ ์—ด ์˜ ์ˆ˜๋ฅผ ์กฐ์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค!

      // spanCount = 3์ธ ๊ฒฝ์šฐ 3์—ด์„ ์ฐจ์ง€ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค. 
      val spanCount = 3
            val layoutManager = GridLayoutManager(requireContext(), spanCount)
            layoutManager.spanSizeLookup =
                object : GridLayoutManager.SpanSizeLookup() {
                    override fun getSpanSize(position: Int): Int {
                        return when (moviePosterAdapter?.getItemViewType(position)) {
                        
                        // ๋กœ๋”ฉ์˜ ๊ฒฝ์šฐ 3์—ด์„ ์ฐจ์ง€ํ•˜๋„๋ก ํ–ˆ๊ณ  ์ผ๋ฐ˜ ์•„์ดํ…œ์€ 1์—ด์„ ์ฐจ์ง€ํ•˜๋„๋ก ํ•ด์ฃผ์—ˆ๋‹ค.
                            MoviePosterAdapter.VIEW_TYPE_LOADING -> spanCount
                            else -> 1
                        }

     

    ์ด๋Š” ์ถ”ํ›„ ์—ด์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋‹ค๋ฅธ ํƒญ ๋ ˆ์ด์•„์›ƒ์—์„œ ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋„ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜์—ˆ๋‹ค.

     

    ์—ฌ๊ธฐ๊นŒ์ง€์˜ ๊ฒฐ๊ณผ๋Š” ์งœ์ž” ๋กœ๋”ฉ์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.(๊ทธ๋Ÿฐ๋ฐ ์•„์ดํ…œ์ด ํ•œ ํ–‰ ํ†ต์ฑ„๋กœ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋“œ๋ฌผ์–ด์„œ ๋กœ๋”ฉ๋„ ์—†๋Š” ์นธ์—์„œ๋งŒ ๋‚˜ํƒ€๋‚ฌ๋‹ค) 

     

    ๋์ด ๋‚œ๊ฑฐ์•ผ? ๋ฐ์ดํ„ฐ๊ฐ€ ์˜ค๊ณ  ์žˆ๋Š”๊ฑฐ์•ผ?

    ๊ทธ๋Ÿฐ๋ฐ ํ•œ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ์˜ค๊ณ  ์žˆ๋Š” ์ค‘์ธ์ง€, ๋์ด ๋‚˜์„œ ์˜ค์ง€ ์•Š๋Š”์ง€ ํŒ๋‹จํ•˜๋Š” ๋กœ์ง์„ ์ž‘์„ฑํ•ด์ฃผ์ง€ ์•Š์•„์„œ 

    ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค ๊ฐ€์ ธ์˜จ ๊ฒฝ์šฐ, ์ฆ‰ ์ตœํ•˜๋‹จ์œผ๋กœ ์Šคํฌ๋กค ํ•œ ๊ฒฝ์šฐ์—๋„ ๋กœ๋”ฉ์ด ๋‚˜ํƒ€๋‚ฌ๋‹ค.

     

    ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€์ธ์ง€๋ฅผ ์–ด๋Œ‘ํ„ฐ์—๊ฒŒ ์•Œ๋ ค์ฃผ๋Š” ๋กœ์ง์ด ํ•„์š”ํ–ˆ๋‹ค.

    ๋”ฐ๋ผ์„œ  ์–ด๋Œ‘ํ„ฐ์— ์•„๋ž˜์™€ ๊ฐ™์€ ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค.

     fun isLastPage() {
            isLastPage = true
        }

     

    ๋˜ํ•œ getItemViewType ๋ฉ”์„œ๋“œ์—์„œ isLastPage๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ์—๋งŒ ๋กœ๋”ฉ ํ™”๋ฉด์ด ๋œจ๋„๋ก ํ•ด์ฃผ์—ˆ๋‹ค.

     override fun getItemViewType(position: Int): Int {
            return if (position == posterUriList.size - 1 && !isLastPage) VIEW_TYPE_LOADING else VIEW_TYPE_ITEM
        }

     

    ํ”„๋ž˜๊ทธ๋จผํŠธ ์ƒ์—์„œ๋„ ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€์ผ ๊ฒฝ์šฐ ๋ทฐ๋ชจ๋ธ์—์„œ ํ”„๋ž˜๊ทธ๋จผํŠธ๋กœ NotifyLastPage ๋ผ๋Š” effect๋ฅผ ๋ณด๋‚ด๋„๋ก ํ•˜๊ณ , ์–ด๋Œ‘ํ„ฐ์˜ ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€์ž„์„ ์•Œ๋ ค์ฃผ์—ˆ๋‹ค.

    is MovieSelectEffect.NotifyLastPage -> {
                    moviePosterAdapter?.setLoading(false)
                    moviePosterAdapter?.isLastPage()
                    Toast.makeText(context, "๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€ ์ž…๋‹ˆ๋‹ค!", Toast.LENGTH_SHORT).show()

     


    ์•ž์œผ๋กœ๋„ ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•ด์•ผํ• ๊นŒ??? 

    ์ด๋ ‡๊ฒŒํ•˜์—ฌ ๋ฌดํ•œ์Šคํฌ๋กค๊ณผ ๋กœ๋”ฉํ™”๋ฉด ์ถ”๊ฐ€๊นŒ์ง€ ์™„์„ฑ์„ ํ–ˆ๋‹ค. 

    ๊ทธ๋Ÿฐ๋ฐ ๋ฌดํ•œ์Šคํฌ๋กค์„ ๊ตฌํ˜„ํ•  ๋•Œ๋งˆ๋‹ค ์ด ๊ณผ์ •์„ ๋‹ค ๊ฑฐ์ณ์•ผํ• ๊นŒ??! ๐Ÿคฃ

    ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๊ฐ์ƒ๋ฌธ ๋ฐ์ดํ„ฐ, ๋Œ“๊ธ€, ์˜ํ™” ๋“ฑ์„ ๋ชจ๋‘ ๋ฌดํ•œ ์Šคํฌ๋กค๋กœ ๊ตฌํ˜„ํ•ด์•ผํ•œ๋‹ค.

    ๊ทธ๋Ÿฐ๋ฐ ์ˆ˜๋™์œผ๋กœ ๋‹ค ๊ตฌํ˜„ํ•˜๋‹ค๋ณด๋‹ˆ ํŽ˜์ด์ง• ์‹œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ๊ณ  ์ฝ”๋“œ ๋ฐ˜๋ณต์ด ๋งŽ์•„์ง„๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค. 

     

    ๋”ฐ๋ผ์„œ ๊ทธ๋™์•ˆ ๋งŽ์ด ๋“ค์–ด๋ณด์•˜๋˜ Paging3์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ด ๋ฌด์—‡์ผ๊นŒ๋ฅผ ์‚ดํŽด๋ณด๋‹ค๊ฐ€ ๋‚ด๊ฐ€ ์ˆ˜๋™์œผ๋กœ ๊ตฌํ˜„ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ๋˜์—ˆ๋‹ค....!!!!!!!! 

    ์—„์ฒญ๋‚ฌ๋‹ค. ๋”ฐ๋ผ์„œ Paging3๋ฅผ ์ ์šฉํ•ด์„œ ์–ผ๋งˆ๋‚˜ ํฐ ์ฐจ์ด๊ฐ€ ์žˆ์„์ง€ ์•Œ์•„๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.

    ๊ทธ ๊ณผ์ •์€ ๋‹ค์Œ ๊ธ€๋ถ€ํ„ฐ ๊ธฐ๋กํ•ด๋ณด๋„๋ก ํ•œ๋‹ค :) 

     

    ์Šคํฌ๋กค ์ˆ˜๋™ ๊ตฌํ˜„ ๋!! ๊ณ ์ƒํ–ˆ๋‹น

    728x90