列表中自動播放視頻,常規方案是在每個 xml 中寫入視頻佈局,然後在滑動時獲取當前的下標,播放此下標的視頻 弊端:播放容易出錯,需要精準控制好停止播放操作,並且適配器中容易觸發多次刷新,導致執行多次同樣的操作,不易控制離開停止等操作,增加了佈局的負擔,影響滑動流暢度,無法復用... 使用過的都比較清 ...
列表中自動播放視頻,常規方案是在每個 xml 中寫入視頻佈局,然後在滑動時獲取當前的下標,播放此下標的視頻
弊端:播放容易出錯,需要精準控制好停止播放操作,並且適配器中容易觸發多次刷新,導致執行多次同樣的操作,不易控制離開停止等操作,增加了佈局的負擔,影響滑動流暢度,無法復用...
使用過的都比較清楚這些弊端,所以需要一套統一的播放邏輯控制,並且播放中的視頻只有一個,方便控制
大致思路就是在當前的下標佈局中,動態註入一個視頻佈局,然後去控制這個佈局的狀態,滑動時移除
優點:跟展示列表分離,容易控制,可復用,不影響列表滑動流暢度
實現流程
1、在xml中編寫好播放佈局,然後 inflate 載入佈局 videoLayout,並且綁定生命周期控制釋放,在把需要監聽的 Recyclerview 傳進來,設置好滑動監聽
2、獲取到當前下標,並且拿到該下標(viewholder)的根佈局
3、拿到該下標的實體類(播放路徑等)
4、拿到的根佈局調用系統方法 viewholderRoot.addView(videoLayout) ,把需要播放的佈局添加進 viewholder 中
5、使用 WeakReference 弱引用持有當前工具類,然後在 Handler 中去控制播放等方法
private class WeakReferenceHandler(tag: AutoPlayVideoUtils) : Handler() { private val mView = WeakReference(tag) override fun handleMessage(msg: Message) { when (msg.what) { MSG_LOAD_VIDEO -> mView.get()?.startVideo(msg.obj as VideoData) } } }
6、在監聽的滑動事件中判斷可見範圍,然後移除播放佈局 videoLayout
root?.parent?.let { if (it is ViewGroup) { val video = root.findViewById<VideoPlayerView>(R.id.video_player_view) if (video?.isPlaying == true) { video.pause() video.stop() } it.removeView(root) videoPlayerView = null rootView = null } }
此時基本流程完成
實際項目中還有很多需要處理
比如滑動時如果可見下標想等,需要跳過邏輯,不用執行播放操作,然後滑動中監聽是否可見,什麼時候添加佈局跟移除佈局
比如在生命周期中恢復,暫停,釋放
所幸 Recyclerview 中有滑動停止監聽,可以很好的監聽控制