Author: Cang Wang Time: July 17, 2018
The following is my series of related articles, you can refer to, you can give a like or follow my article.
[Android] How to make a chapter list of apps with a crash rate of less than three per thousand
Now many live broadcast software have the function of infinite loop loading and group chat picture preview. This section will analyze the implementation of this function.
1.ViewPager creates an infinite loop
2.RecylerView slides so that it can be fixed in one of the full cells
3. Customize View and Layout to achieve sliding effect.
So let me show you what ViewPager does. It requires at least four views to reuse objects
private fun initView() {// Initialize multiplexed preview interface,4 are enough for sliding schedulingfor (i in0.. 3) {val previewView = MediaPreviewView(this) previewview. tag = I previewview. add(previewView) mediaview_viewpager.adapter = object :PagerAdapter() {
override fun instantiateItem(container: ViewGroup, position: Int): Any {
Log.i(TAG, "View index = ${(position) % 4}, position = $position, current position = $currentPosition") val message = mediaItems[position] val previewView = previewViews[(position) %4 previewView.setMediaItem(message)if(previewview. parent == null) {// addView container. AddView (previewView)}returnOverride Fun destroyItem(container: ViewGroup, position: Int, object ': Any) { val previewView = previewViews[(position) % 5] previewView.clear() } override fun isViewFromObject(view: View, `object`: Any): Boolean {returnView == 'object'} override fun getCount() = mediaItems. Size Override fun getItemPosition(' object ': Any): Int {return if ((`object` as View).tag as Int == (currentPosition) % 5) {
POSITION_UNCHANGED
} else{POSITION_NONE}}} / / add slide monitoring mediaview_viewpager addOnPageChangeListener (object: ViewPager.OnPageChangeListener { override fun onPageScrollStateChanged(state: Int) {} override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {} override fun onPageSelected(position: Int) {if(position ! = currentPosition) { currentPosition = position lastIndexId = mediaItems[position].indexIdif(position == 0) {getForwardMessages()}if(position == mediaitems.lastIndex) {getBackwardMessages()}}}})}Copy the code
Here, the ViewPager forces you to refresh the screen when the data changes. If you swipe to get a data address on the network, ViewPager forces a refresh, and you suddenly see a black screen… It was a really bad experience…
Viewpager does not provide a partial refresh method, so this bug cannot be fixed unless you rewrite the entire Viewpager, which is not good for subsequent maintenance optimizations.
You can do this if the slide is cyclic and the number is fixed, but you can’t if you need to update the data dynamically, and the experience is poor. Live sliding and online image rotation require dynamic loading, so this scheme is not suitable.
2. Use RecylerView card scheme, here is very simple, only PagerSnapHelper directly associated with RecylerView, ReyclerView will directly complete View reuse. RecylerView has a partial refresh interface, so it doesn’t have a splash screen.
private fun initView() {
mediaview_recycler.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
mediaview_recycler.adapter = MediaViewAdapter()
mediaview_recycler.isNestedScrollingEnabled = falsePagerSnapHelper(). Apply {attachToRecyclerView(MediaView_recycler)}}Copy the code
Partial forward flush
private fun getForwardMessages() {
mediaItems.addAll(0, it)
mediaview_recycler.adapter.notifyItemRangeInserted(0, it.size)
mediaview_recycler.adapter.notifyItemRangeChanged(0, mediaItems.size)
}
Copy the code
Partial backward refresh
private fun getBackwardMessages() {
if (it.isNotEmpty()) {
mediaItems.addAll(it)
mediaview_recycler.adapter.notifyItemInserted(mediaItems.size - it.size)
}
}
Copy the code
SnapHelper also has a LinearSnapHelper with a center effect
If you also need to determine the timing of the video, you need to duplicate the LayoutManager method. You can refer to the following article in Android to imitate tiktok’s sliding RecycleView implementation
There is this open source library for PageRecylerView, but it reflects the mViewFlinger object that uses RecylerView, which is not available on Google Play if it goes live.
https://github.com/ckrgithub/PageRecyclerView
This open source layout was written by Daishen five years ago and feels like the original ViewPager. Data changes also need to brush the whole page, so there will be a flash screen problem, need to rewrite the page refresh mode to local refresh.
https://github.com/castorflex/VerticalViewPager
… 2018.7.17 update… 1. If there is a progress bar in the player, recylerView needs to be divided into a region where the touch events are passed down and the override intercepts the events.
var canSmoothDownSide = false //trueIt means you can slide,falseOverride fun onInterceptTouchEvent(e: MotionEvent?) : Boolean {if(e? .action == MotionEvent.ACTION_MOVE && ! canSmoothDownSide) {if (e.rawY > ScreenUtils.getScreenHeight(context) - ScreenUtils.dp2Px(context, 80f)) {
return false}}return super.onInterceptTouchEvent(e)
}
Copy the code
2. Play with Exoplayer, play (True) and pause (false) with setPlayWhenReady. If you pause with stopVideo, when recylerView slides and returns, the screen will be black. An ExoPlayerView cannot be replaced with a prepare MediaSource twice, otherwise AudioFlinger could not create Task will be displayed.
3.Exoplayer, how to recover the video is too short (1~3 seconds) will have a black screen problem. Sometimes the video will not play because the recylerView cannot be stuck in the stopped frame. The solution is to use RecylerView onChildViewAttachedToWindow, reset the broadcast schedules.
Star Technology Group QQ: 557247785.