Kristy Welsh
Kristy Welsh

Reputation: 8530

Android tabs adapter shows nulled out fragments depending on which tab I'm in

I implemented a ActionBarSherlock with a ViewPager and a TabsAdapter. It works fine until I try to communicate between fragments.

I've 3 Tabs in my Application, and I can click on each of the tabs no problem, but when communicating through an interface, in two out of three tabs, one of my fragments in my tab is null. This happens when I select a menu item. I want selecting a menu item to be communicated to all fragments in the ViewPager. However, when I'm in tab[0], tab[2] is null but tabs[0] and tab[1] are not null. When I'm in tab[2], tab[0] is null, but tab[1] and tab[2] are not null. However, when I'm in tab[1], no fragments are null.

All the fragments are visible when I click on each of the tabs. That's not a problem.

The Code:

public class GPSTrackingActivity extends SherlockFragmentActivity implements DistanceFragment.OnCoordinatesAddedListener, ReportsFragment.ReportStartDateListener
{


     long insertedID = 0;
private Menu menu;
//for shared preferences
private static final String KEY_UNITS = "units";
private static final String KEY_START_POSITION = "start";
ViewPager mViewPager;
TabsAdapter mTabsAdapter;
String TAG = "GPSTrackingActivity";
//set 0 for miles, 1 for kilometers
int mMilesOrKilometers = 0;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //setContentView(R.layout.main);

  //create a new ViewPager and set to the pager we have created in Ids.xml
    mViewPager = new ViewPager(this);
    mViewPager.setId(R.id.pager);
    setContentView(mViewPager);

    ActionBar actionBar = getSupportActionBar(); 
    actionBar.setDisplayShowTitleEnabled(false); 
    actionBar.setDisplayShowHomeEnabled(false);
    actionBar.setNavigationMode ( ActionBar . NAVIGATION_MODE_TABS );

    //if user has previous settings, get them from shared prefs. 
    getSharedPrefs();

    mTabsAdapter = new TabsAdapter(this, mViewPager);
    mTabsAdapter.addTab(actionBar.newTab().setText(" Track").setIcon(R.drawable.browser_compass_icon),
            DistanceFragment.class, null);
    mTabsAdapter.addTab(actionBar.newTab().setText(" Trips").setIcon(R.drawable.folder_chart_icon),
            TripsFragment.class, null);
    mTabsAdapter.addTab(actionBar.newTab().setText(" Report").setIcon(R.drawable.mail_compose_icon),
            ReportsFragment.class, null);

}    



/* set the units of measurement for all the fragments
 */
public void ChangeUnitsOfMeasure() { 
    try { 
        DistanceFragment DistanceFrag = (DistanceFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":0");
        if (DistanceFrag != null && DistanceFrag.getView() != null) {
                Log.d(TAG,"Class=" + DistanceFrag.getClass());
                      Log.d(TAG,"Found the Distance Fragment");
                      DistanceFrag.ClearData();
                      DistanceFrag.setMileOrKilometers(mMilesOrKilometers);
         }
        TripsFragment TripsFrag = (TripsFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":1");
        if (TripsFrag != null && TripsFrag.getView() != null) {
                Log.d(TAG,"Class=" + TripsFrag.getClass());
                if (TripsFrag.getClass() == TripsFragment.class) {
                      Log.d(TAG,"Found the Trips Fragment");
                      TripsFrag.setMileOrKilometers(mMilesOrKilometers);
                 }
         }
        ReportsFragment ReportsFrag = (ReportsFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":2");

        if (ReportsFrag != null && ReportsFrag.getView() != null) {
                Log.d(TAG,"Class=" + ReportsFrag.getClass());
                          Log.d(TAG,"Found the Reports Fragment");
                      ReportsFrag.setMileOrKilometers(mMilesOrKilometers);
         }

    }
    //in case we change the getCurrentItem() value to anything other than 1
    //would expect a ClassCastException
    catch (Exception e) { 
        Log.d(TAG,String.valueOf(e));
    }
}


@Override
public boolean onOptionsItemSelected(MenuItem item)
{ 
    //check selected menu item
    switch (item.getItemId()) { 
    case R.id.miles: 
        mMilesOrKilometers = 0;
        ChangeUnitsOfMeasure();
        return true;
    case R.id.kilometers: 
        mMilesOrKilometers = 1;
        ChangeUnitsOfMeasure();
        return true;
    //quit program
    case R.id.menu_quit:
      finish();
      return true;
    default: 
      return super.onOptionsItemSelected(item);
    }
}

//called from ReportsFragment
public void getCurrentIdOfFragment() { 
    int mCurrentItem = mViewPager.getCurrentItem();
    Log.d(TAG,"Current View Page=" + String.valueOf(mCurrentItem));
}



// create TabsAdapter to create tabs and behavior
public class TabsAdapter extends FragmentPagerAdapter
 implements ActionBar.TabListener, ViewPager.OnPageChangeListener {

 private final Context mContext;
       private final ActionBar mActionBar;
       private final ViewPager mViewPager;
       private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

       final class TabInfo {
           private final Class<?> clss;
           private final Bundle args;

           TabInfo(Class<?> _class, Bundle _args) {
               clss = _class;
               args = _args;
           }
       }

 public TabsAdapter(SherlockFragmentActivity activity, ViewPager pager) {
  super(activity.getSupportFragmentManager());
           mContext = activity;
           mActionBar = activity.getSupportActionBar();
           mViewPager = pager;
           mViewPager.setAdapter(this);
           mViewPager.setOnPageChangeListener(this);
       }

 public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
           TabInfo info = new TabInfo(clss, args);
           tab.setTag(info);
           tab.setTabListener(this);
           mTabs.add(info);
           mActionBar.addTab(tab);
           notifyDataSetChanged();

       }



 @Override
 public void onPageScrollStateChanged(int state) {
  // TODO Auto-generated method stub

 }

 @Override
 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
  // TODO Auto-generated method stub

 }

 @Override
 public void onPageSelected(int position) {
  // TODO Auto-generated method stub
  mActionBar.setSelectedNavigationItem(position);
 }

 @Override
 public void onTabReselected(Tab tab, FragmentTransaction ft) {
  // TODO Auto-generated method stub

 }

 @Override
 public void onTabSelected(Tab tab, FragmentTransaction ft) {
    Object tag = tab.getTag();
    for (int i=0; i<mTabs.size(); i++) {
        if (mTabs.get(i) == tag) {
            mViewPager.setCurrentItem(i);
        }
    }
 }

 @Override
 public void onTabUnselected(Tab tab, FragmentTransaction ft) {
  // TODO Auto-generated method stub

 }

 public Fragment getItem(int position) {
     TabInfo info = mTabs.get(position);
     //Fragment mFragment = Fragment.instantiate(mContext, info.clss.getName(), info.args);
     return (Fragment) Fragment.instantiate(mContext, info.clss.getName(), info.args);
    }


 @Override
 public int getCount() {
  return mTabs.size();
 }

}   

}

It's all happening when I call the ChangeUnitsOfMeasure() function due to menu items being selected. I know the fragments are null because I test for the fragments being null before calling a function in the fragments. My LogCat (see code) is reporting showing only fragments[0] and [1] or fragments[1] and [2] or fragments [0], [1] and [2] being found, depending on what tab I am in.

Really Weird behavior!

Upvotes: 0

Views: 556

Answers (1)

Kristy Welsh
Kristy Welsh

Reputation: 8530

I found the answer. It has to do with the ViewPager.setOffscreenPageLimit(), which is set by default to 1. Increasing the limit to 2 allowed me to access all fragments at one time.

mViewPager.setOffscreenPageLimit(2);

I found the answer here: My fragments in viewpager tab dont refresh.

Upvotes: 2

Related Questions