CDrosos CDrosos - 19 days ago 9
Android Question

Reloading/Refreshing Fragments in ViewPager/Tab implementation on a non-visible cached Fragment with custom Adapter

Im using tab layout (with ViewPager, it's Adapter is an extension of FragmentStatePagerAdapter and TabLayout) and im trying to refresh a listview on tab2 when i click on a button on tab1.
Im doing this job from the activity that holds the viewpager for now because i dont know any other way to do it.
The way i refresh it is to:


  1. Monitor OnTabSelected of ViewPager

  2. When tab2 become Visible, refresh the ListView with something like this:

    View _list = Activity.FindViewById(Resource.Id.MessagesListView);
    var _adapter = new MessagesAdapter(Activity, null);
    _adapter.NotifyDataSetChanged();
    _adapter = new MessagesAdapter(Activity, _reviewList);
    var _listview= (ListView)_list;
    _listview.Adapter = _adapter;
    _adapter.NotifyDataSetChanged();



As you might understand from the code, my problem is that the ListView doesnt replace its items, it only adds them in top of the others, how i can clear the listview?

I have also try with no luck with .RemoveViews(0, test.ChildCount);
My listview adapter is a simple extension of the BaseAdapter.

Also if you have another better way of Refreshing ListView or Fragment im open to suggestions

EDIT:

My final Adapter that works pretty well, if anyone has more suggestions to make it even better please make a comment

using Android.Support.V4.App;
using Android.Util;
using Java.Lang;

using Fragment = Android.Support.V4.App.Fragment;

namespace StaffPro
{
public class TabsFragmentPagerAdapter : FragmentStatePagerAdapter
{
private readonly Fragment[] fragments;

private readonly ICharSequence[] titles;

SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();

public TabsFragmentPagerAdapter(FragmentManager fm, Fragment[] fragments, ICharSequence[] titles) : base(fm)
{
this.fragments = fragments;
this.titles = titles;
}
public override int Count
{
get
{
return fragments.Length;
}
}

public override Fragment GetItem(int position)
{
return fragments[position];
}

public override ICharSequence GetPageTitleFormatted(int position)
{
return titles[position];
}
public override void DestroyItem(Android.Views.View container, int position, Java.Lang.Object objectValue)
{

registeredFragments.Remove(position);
base.DestroyItem(container, position, objectValue);
}
public override Java.Lang.Object InstantiateItem(Android.Views.ViewGroup container, int position)
{
Fragment fragment = (Fragment)base.InstantiateItem(container, position);
registeredFragments.Put(position, fragment);
return fragment;
}
public Fragment GetRegisteredFragment(int position)
{
return registeredFragments.Get(position);
}
}
}

Answer

You could call a refresh directly within that fragment from the parent activity.

You'll need to implement on your ViewPager Adaptor a way for returning the fragment, so something like this:

    public override void DestroyItem(View container, int position, Object @object)
    {
        registeredFragments.Remove(position);
        base.DestroyItem(container, position, @object);
    }

    public override Object InstantiateItem(ViewGroup container, int position)
    {
        Android.Support.V4.App.Fragment fragment = (Android.Support.V4.App.Fragment)base.InstantiateItem(container, position);
        registeredFragments.Put(position, fragment);
        return fragment;
    }

    public Android.Support.V4.App.Fragment GetRegisteredFragment(int position)
    {
        return registeredFragments.Get(position);
    }

Then in your main activity:

    public void UpdateFragment()
    {
        var activeFragment = _Adaptor.GetRegisteredFragment(1); // where in the viewpager the fragment is
        ((YourFragment)activeFragment).MethodOnFragment();
    }
Comments