1. 程式人生 > 其它 >Android技術分享| ViewPager2離屏載入,實現抖音上下視訊滑動

Android技術分享| ViewPager2離屏載入,實現抖音上下視訊滑動

要實現類似抖音上下滑動小視訊的絲滑效果,需要有一個預載入的功能。所謂的預載入,

就是需要在顯示當前頁的情況下,提前將當前頁後面的內容載入,以保證使用者滑動到下一個視訊的時候,

可以減少等待時間,在正常網速下,可以做到絲滑瀏覽。

在 ViewPager2 第四個版本中加入了一個新功能:setOffscreenPageLimit

setOffscreenPageLimit(int limit)

引數:limit 有多少頁面將在任一側保持在螢幕外。有效值為 >= 1 和 預設值 -1

說明:設定應保留在當前可見頁面任一側的頁面數。超出此限制的頁面將在需要時從介面卡重新建立。設定的值必須大於0或者預設值-1。當前頁面的前後(limit數)頁面會被新增到檢視層次結構中,即使它是不可見的,超出limit數將會從檢視刪除,但會像 RecyclerView一樣被回收。

通過方法說明可以知道,這個特性簡直就是做這種功能的神器呀,但能否實現預期效果。

我們簡單寫一個 Demo 測試一下,在滑動時候,View 的生命週期,這樣我們就可以在合適的回撥方法裡建立。銷燬播放器,暫停/播放視訊。

使用:

dependencies {
    implementation("androidx.viewpager2:viewpager2:1.0.0")
}

Adapter

 inner class VPAdapter() :
        RecyclerView.Adapter<VPAdapter.BaseViewHolder?>() {

        override fun onCreateViewHolder( parent: ViewGroup, viewType: Int): BaseViewHolder {
            val itemView: View = LayoutInflater.from(parent.context).inflate(R.layout.vp_item_layout, parent, false)
            return BaseViewHolder(itemView)
        }

        override fun onBindViewHolder( holder: BaseViewHolder, position: Int) {

        }

        override fun getItemCount(): Int {
            return dataArray.size
        }

        override fun onViewDetachedFromWindow(holder: BaseViewHolder) {
            super.onViewDetachedFromWindow(holder)
            Log.d("ViewPager2","View 離屏 第${holder.adapterPosition+1}頁")
        }

        override fun onViewAttachedToWindow(holder: BaseViewHolder) {
            super.onViewAttachedToWindow(holder)
            Log.d("ViewPager2","View 加入螢幕 第${holder.adapterPosition+1}頁")
        }

        inner class BaseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            var root: RelativeLayout?
            var image :TextView?
            init {
                root = itemView.findViewById(R.id.root)
                image =  itemView.findViewById(R.id.iv_test)
            }
        }
    }

準備10條資料,設定offscreenPageLimit為1,則在螢幕上的頁數一直都是3頁。預期是第一頁的時候,會建立第二頁。滑動到第二頁的時候,建立第三頁。滑動到第三頁的時候,建立第四頁,並且第一頁走 onViewDetachedFromWindow,從檢視刪除。接下來我們滑動,看下日誌。

進入頁面
ViewPager2: View 加入螢幕 第1頁
ViewPager2: View 加入螢幕 第2頁

滑動到第二頁
ViewPager2: View 加入螢幕 第3頁

滑動到第三頁
ViewPager2: View 加入螢幕 第4頁
ViewPager2: View 離屏 第1頁

滑動到第四頁
ViewPager2: View 加入螢幕 第5頁
ViewPager2: View 離屏 第2頁

返回第三頁
ViewPager2: View 加入螢幕 第2頁
ViewPager2: View 離屏 第5頁

可見,日誌輸入完全符合我們的預期,除了第一頁後,檢視中永遠都會有三頁在上面。

我們只需要在對應的回撥中建立播放器,暫停播放,銷燬播放器即可。如下

 在View加入視窗的回撥中,建立播放器,開始播放隨後暫停⏸️
 override fun onViewAttachedToWindow(holder: BaseViewHolder) {
            super.onViewAttachedToWindow(holder)
            Log.d("ViewPager2","View 加入螢幕 第${holder.adapterPosition+1}頁")
            val player =createArLivePlayer()
            dataArray[holder.adapterPosition].player=player
         		player.startPlay("url")
         		player.pause()
        }
在View離開視窗的回撥中,銷燬播放器
override fun onViewDetachedFromWindow(holder: BaseViewHolder) {
            super.onViewDetachedFromWindow(holder)
           Log.d("ViewPager2","View 離屏 第${holder.adapterPosition+1}頁")
           
            dataArray[holder.adapterPosition].player.release()
        }

建立播放器就暫停,這樣播放器就可以緩衝下一頁的視訊資料,那我們需要再找個地方將當前正在顯示的頁面的播放器開始播放。

只需註冊 ViewPager2的翻頁監聽,播放當前頁的播放器,暫停其他頁面的播放即可。

binding.vp.registerOnPageChangeCallback(object :ViewPager2.OnPageChangeCallback(){
            override fun onPageSelected(position: Int) {
                super.onPageSelected(position)
                dataArray.forEachIndexed { index, videoData ->
                    if (index==position){
                            dataArray[index].player?.resumePlay()
                            Log.d("ViewPager2","當前${index}播放")
                        }

                    }else{
                            dataArray[index].player?.pause()
                             Log.d("ViewPager2","當前${index}暫停")
                        }
                    }
                }
            }
        })

執行,發現效果非常的絲滑,如圖所示。所以說 ViewPager2非常適合做類似場景的需求~