For those who still have issues, do like what I did. I wish it will save your time. It is in Xamarin.Android, but idea should be same in java and kotlin
Prepare your Adapter classes with ClearFragments method through an abstract class:
public abstract class BaseAdapter : FragmentStateAdapter
{
public BaseAdapter(FragmentManager fm, Lifecycle lifecycle) : base(fm, lifecycle)
{
this.fm = fm;
}
readonly FragmentManager fm;
public override int ItemCount => ITEM_COUNT;
private readonly List<Fragment> fragments = new List<Fragment>();
public override Fragment CreateFragment(int position)
{
var fragment = new MyFragment();
fragments.Add(fragment);
return fragment;
}
public void ClearFragments()
{
if (fragments.Count > 0)
{
var transaction = fm.BeginTransaction();
foreach (var fragment in fragments)
{
transaction.Remove(fragment);
}
if (!fm.IsDestroyed)
{
transaction.CommitNow();
}
//see note of Dispose(disposing)
foreach (var fragment in fragments)
{
fragment.Dispose();
}
fragments.Clear();
}
}
private bool disposedValue = false;
//Important note: Your fragment might use Context. You need to override Dispose(disposing) in your fragment class
//and ensure you do not use Context after you dispose it here
protected override void Dispose(bool disposing)
{
if (!disposedValue)
{
disposedValue = true;
if (disposing)
{
ClearFragments();
}
base.Dispose(disposing);
}
}
}
public Adapter1 : BaseAdapter
{
public Adapter1(FragmentManager fm, Lifecycle lifecycle) : base(fm, lifecycle)
{
}
}
public Adapter2 : BaseAdapter
{
public Adapter2(FragmentManager fm, Lifecycle lifecycle) : base(fm, lifecycle)
{
}
}
Then when you want to change adapter, do like this:
public MainActivity : AppCompatActivity
{
private void UseAdapter2()
{
var oldAdapter = viewPager.Adapter as BaseAdapter;
oldAdapter?.ClearFragments();
viewPager.Adapter = null;
var adapter = new Adapter2(SupportFragmentManager, Lifecycle);
// Do any logic that makes this adapter different from the previous one.
viewPager.Adapter = adapter;
oldAdapter?.Dispose();
}
}