I've spent a bit of time with this, and I've diagnosed the problem for anyone who needs to hear it. I tried to keep my solution as conventional as possible. If we look at your statement:
Therefore the adapter will be recreated when I navigate back to the
HomeFragment, which also recreates all Fragments in the Viewpager2 and
the current item is reset to 0.
The problem is that the current item is reset to 0, because the list that your adapter is based off-of is recreated. To resolve the issue, we don't need to save the adapter, just the data inside of it. With that in mind, solving the problem is not difficult at all.
Let's layout some definitions:
- HomeFragmentis, as you've said, the host of your- ViewPager2,
- MainActivityis the running activity which hosts- HomeFragmentand all created fragments inside of it
- We are paging through instances of MyFragment. You could even have more than one type of fragment that you page through, but that's beyond the scope of this example.
- PagerAdapteris your- FragmentStateAdapter, which is the adapter for- HomeFragment's- ViewPager2.
In this example, MyFragment has the constructor constructor(id : Int). Then, PagerAdapter is probably going to appear as follows:
class PagerAdapter(fm : Fragment) : FragmentStateAdapter(fm){
    
    var ids : List<Int> = listOf()
    ...
    
    override fun createFragment(position : Int) : Fragment{
        return MyFragment(ids[position])
    }
    
}
The problem that we are facing is every time you recreate PagerAdapter the constructor is called and that constructor, as we can see above, sets ids to an empty list.
My first thought was that maybe I could switch fm to be MainActivity. I don't navigate out of MainActivity so I'm not sure why, but this solution doesn't work.
Instead, what you need to do is abstract the data out of PagerAdapter. Create a "viewModel":
    /* We do NOT extend ViewModel. This naming just indicates that this is your data- 
    storage vehicle for PagerAdapter*/
    data class PagerAdapterViewModel(
    var ids : List<Int> 
    )
Then, in PagerAdapter, make the following adjustments:
class PagerAdapter(
    fm : Fragment,
    private val viewModel : PagerAdapterViewModel 
) : FragmentStateAdapter(fm){
    
    // by creating custom getters and setters, you are migrating your code to this 
    // implementation without needing to adjust any code outside of the adapter 
    var ids : List<Int>
        get() = viewModel.ids 
        set(value) {viewModel.ids = value} 
    
    override fun createFragment(position : Int) : Fragment{
        return MyFragment(ids[position])
    }
    
}
Finally, in HomeFragment, you'll have something like:
class HomeFragment : Fragment(){ 
    ... 
    /** Calling "by lazy" ensures that this object is only created once, and hence
    we retain the data stored in it, even when navigating away. */
    private val pagerAdapterViewModel : PagerAdapterViewModel by lazy{
        PagerAdapterViewModel(listOf())
    }
    private lateinit var pagerAdapter : PagerAdapter
    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        ...
        pagerAdapter = PagerAdapter(this, pagerAdapterViewModel)
        pager.adapter = pagerAdapter 
        ...
    }
    
    ...
}