ViewPager2 : Initialize fragments only when they are visiblee, and then keep them initialized

Viewed 335

I have 4 fragments managed using ViewPager2.

I want to initialize each fragment only when i open it for the first time, that's means when i open the app, only the first fragment get initialized, and the second fragment will be initialized only when i navigate to it.

This seems the default behavior for the viewpager2 when i don't do any special configuration.

But what I want to do is not lose the instance of the first fragment when I navigate to second fragment.

I tried to use viewpager.isUserInputEnabled = 4 (or 1). this function keep fragments initialized and don't lose their instances. but it initialize all fragments at once, and I only want to initialize them when they are visible.

this is my adapter

class HomeAdapter(fragmentActivity : FragmentActivity) : FragmentStateAdapter(fragmentActivity)
{
    override fun getItemCount() : Int = 4
    
    
    override fun createFragment(position : Int) : Fragment
    {
        return when(position)
        {
            0 -> SearchMissionContainerFragment.instance()
            1 -> MissionHistoryFragment.instance()
            2 -> PaymentContainerView.instance()
            else -> SettingsFragment.instance()
        }
    }
}

and this is the initialization part

binding.viewpager.offscreenPageLimit = 1
binding.viewpager.isUserInputEnabled = false
binding.viewpager.adapter = HomeAdapter(this)

Any solution please?

2 Answers

I couldn't find a solution for this, But anyway what is your problem with this behaviours? If you need a call back for when the fragment is visible you can use onResume callback. And if you want to onResume code not call twice you can set a variable (boolean) to true in the end of onResume and check it's value at first line of onResume.

You can try this link

Set offscreenPageLimit = size and your fragment extends LazyFragment
Implementation override getContentViewId() return R.layout.your_layout this will initialize your layout for first time, but not view.
override initView(), initData(), initEvent() and put your code in these methods.

abstract class LazyFragment : Fragment() {

    private var mContext: Context? = null
    private var isFirstLoad = true // Whether to load for the first time

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mContext = activity
    }


    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = LayoutInflater.from(mContext).inflate(getContentViewId(), null)
        initView(view)
        return view
    }

    override fun onResume() {
        super.onResume()
        if (isFirstLoad) {
        // Put the data loading logic in the onResume() method
            initData()
            initEvent()
            isFirstLoad = false
        }
    }

/**
 * Set layout resource id
 *
 * @return
 */
    protected abstract fun getContentViewId(): Int

/**
 * Initialize the view
 *
 * @param view
 */
    protected fun initView(view: View?) {}

/**
 * Initialization data
 */
    protected fun initData() {}

/**
 * Initialization event
 */
    protected fun initEvent() {}
}
Related