0

In my app, am showing list of month calendar which can be scrollable to previous and next month. While swiping to previous and next, my fragments are loading smoothly and without any delay if I use FragmentStatePagerAdapter and ViewPager but it's now deprecated. So, I updated

ViewPager to ViewPager2 

FragmentStatePagerAdapter to FragmentStateAdapter 

After updating, I can see there is a delay in loading the fragments while swiping previous and next. But the same code works smoothly with FragmentStatePagerAdapter and ViewPager. I also tried mViewPager2.setOffscreenPageLimit(//Interger Value//) but no help.

Please assist me.

Using FragmentStateAdapter and ViewPager2 Using FragmentStatePagerAdapter and ViewPager

fragment_employee_months_holder

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/fragment_months_viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        android:focusable="true" />

    <ProgressBar
        android:id="@+id/progressBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:backgroundTint="@color/colorPrimary" />

</RelativeLayout>

EmployeeSummaryAdapter

class EmployeeSummaryAdapter(
    fragment: Fragment,
    private val mCodes: List<String>,
    private val mListener: NavigationListener,
    private val progressBarInterface: ProgressBarInterface
) : FragmentStateAdapter(fragment) {

    private val mFragments = SparseArray<EmployeeSummaryFragment>()

    override fun createFragment(position: Int): EmployeeSummaryFragment {
        val bundle = Bundle()
        val code = mCodes[position]
        bundle.putString(DAY_CODE, code)

        val fragment = EmployeeSummaryFragment(progressBarInterface)
        fragment.arguments = bundle
        fragment.listener = mListener
        mFragments.put(position, fragment)
        
        return fragment
    }

    override fun getItemCount(): Int = mCodes.size

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }
}

EmployeeSummaryFragmentHolder

class EmployeeSummaryFragmentHolder : MyFragmentHolder(), NavigationListener, ProgressBarInterface {

    private var viewPager2: ViewPager2? = null
    private lateinit var mEmployeeSummaryAdapter: EmployeeSummaryAdapter
    private lateinit var mView: View

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        currentDayCode = Formatter.getTodayCode()
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        mView = inflater.inflate(R.layout.fragment_employee_months_holder, container, false)
        viewPager2 = mView.fragment_months_viewpager
        viewPager2!!.id = (System.currentTimeMillis() % 100000).toInt()

        Handler(Looper.getMainLooper()).postDelayed({
            setupFragment()
        }, 0)

        return mView
    }

    private fun setupFragment() {
        val codes = getMonths(currentDayCode)
        mEmployeeSummaryAdapter = EmployeeSummaryAdapter(this, codes, this, this)
        viewPager2.apply {
            viewPager2!!.adapter = mEmployeeSummaryAdapter

            val myPageChangeCallback = object : ViewPager2.OnPageChangeCallback() {
                override fun onPageScrollStateChanged(state: Int) { }
                override fun onPageScrolled(position: Int, positionOffset: Float, 
                                              positionOffsetPixels: Int) { }
                override fun onPageSelected(position: Int) {   }
            }
            viewPager2!!.registerOnPageChangeCallback(myPageChangeCallback)
        }
    }
}

EmployeeSummaryFragment

class EmployeeSummaryFragment(val progressBarInterface: ProgressBarInterface) :
    Fragment(), MonthlyCalendar {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_employee_month, container, false)
        ...
        ...        
        return view
    }

    override fun onResume() {
        super.onResume()
        ...
        ...
    }
}
Rasool Mohamed
  • 433
  • 7
  • 17

1 Answers1

1

I tried to look into your code and I didn't find anything suspicious, but you definitely need to set your mViewPager2.setOffscreenPageLimit(//Interger Value//) into your EmployeeSummaryFragmentHolder.

viewpager2.offscreenPageLimit = 2
Henrique Vasconcellos
  • 1,144
  • 1
  • 8
  • 13
  • Yeah, I tried adding as you mentioned but still facing the same issue – Rasool Mohamed Aug 25 '21 at 08:27
  • 1
    Are you using the latest viewpager2 library? Other suggestion is try to use debugging and/or reduce your setup complexity? Maybe insert a Log.D in your EmployeeSummaryFragment createView so you can see when the fragment is created? with offscreenPageLimit = 2 the second and third one should be created when you are still in the first one.. – Henrique Vasconcellos Aug 25 '21 at 14:42
  • 1
    One extra thing, the onResume on EmployeeSummaryFragment is only get called when the fragment itself is displayed, so if you have any loading process you should move to onViewCreated. – Henrique Vasconcellos Aug 25 '21 at 15:29
  • 1
    Thanks a lot, I checked in debugging that   1. onResume() is called in all the loaded fragments when I use FragmentStatePagerAdapter and ViewPager. 2. But in FragmentStateAdapter and ViewPager2, onResume() is called only if that fragment is visible on UI. 3. I have loading process in onResume() now I have moved it to onViewCreated() and now it's loading without any delay. Accepted and Upvoted your answer and comments. – Rasool Mohamed Aug 26 '21 at 05:54