0

I have an activity with 3 tabs using fragments, it works fine when working in portrait mode, however, when I change it to landscape, it crashes. This is the code:

public class MainMenuActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_menu);

        ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        String label1 = getResources().getString(R.string.userMainTab);
        Tab tab = actionBar.newTab();
        tab.setText(label1);
        TabListener<UserTabActivity> tl = new TabListener<UserTabActivity>(this, label1, UserTabActivity.class);
        tab.setTabListener(tl);
        actionBar.addTab(tab);

        String label2 = getResources().getString(R.string.credentialGroupMainTab);
        Tab tab2 = actionBar.newTab();
        tab2.setText(label2);
        TabListener<CredentialGroupActivity> tl2 = new TabListener<CredentialGroupActivity>(this, label2, CredentialGroupActivity.class);
        tab2.setTabListener(tl2);
        actionBar.addTab(tab2);

        String label3 = getResources().getString(R.string.credentialTabHeader);
        Tab tab3 = actionBar.newTab();
        tab3.setText(label3);
        TabListener<CredentialTabActivity> tl3 = new TabListener<CredentialTabActivity>(this, label2, CredentialTabActivity.class);
        tab3.setTabListener(tl3);
        actionBar.addTab(tab3);     

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return true;
    }   

    public static class TabListener<T extends Fragment> implements ActionBar.TabListener{

        private Fragment mFragment;
        private final Activity mActivity;
        private final String mTag;
        private final Class<T> mClass;

        public TabListener(Activity activity, String tag, Class<T> clz){
            mActivity = activity;
            mTag = tag;
            mClass = clz;

            mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
            if(mFragment != null && !mFragment.isDetached()){
                FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
                ft.detach(mFragment);
                ft.commit();
            }
        }

        @Override
        public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
            // TODO Auto-generated method stub
        }

        @Override
        public void onTabSelected(Tab arg0, FragmentTransaction arg1) {
            // TODO Auto-generated method stub
            if(mFragment == null){
                mFragment = Fragment.instantiate(mActivity, mClass.getName());
                arg1.add(android.R.id.content, mFragment, mTag);
            } else{
                arg1.attach(mFragment);
            }
        }

        @Override
        public void onTabUnselected(Tab arg0, FragmentTransaction arg1) {
            // TODO Auto-generated method stub
            if(mFragment != null){
                arg1.detach(mFragment);
            }
        }

    }

}

Could you tell me why is not working? The error is:

java.lang.RuntimeException: Unable to destroy activity{ACTIVITY_NAME} : java.lang.NullPointerException

I have noticed that it fails until I click on any of the tabs, and then try to change it to landscape, but I haven't been able to identify in the code what's happening, and also, when I change the view, it loses the tab where it was positioned.

Thanks in advanced!

EDIT

In order to keep the selected tab after changing the orientation, I ended up doing this, thanks to the suggestions made by Nathaniel Waggoner and karthikk:

protected void onSaveInstanceState(Bundle outState) {
    // TODO Auto-generated method stub
    super.onSaveInstanceState(outState);

    outState.putInt("tabState", actionBar.getSelectedTab().getPosition());
}

//In the onCreate method
    if(savedInstanceState != null ){
        actionBar.selectTab(actionBar.getTabAt(savedInstanceState.getInt("tabState")));
    }

Thanks!!

saman0suke
  • 762
  • 1
  • 8
  • 24

2 Answers2

3

To retain the tab selection,

  1. it has to be stored in preference OR
  2. Override the onSaveInstanceState() and save the TAB_SELECTION. On configuration change your activity would give the previous state as Bundle via onRestoreInstanceState() API.

I suggest to refer http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle) for more information.

karthikk
  • 96
  • 5
1

Are you Overriding onDestroy in your fragments? That NPE you show is a symptom I've seen when I've overidden OnDestroy in fragments used in Tabs. I would remove that override if you are and see if this clears up that issue.

Nathaniel D. Waggoner
  • 2,856
  • 2
  • 19
  • 41
  • I have the onDestroy method in each fragment. I commented the overrides and it works now! THANKS! however, I have one question; I was using the onDestroy method to close a database connection, I thought it was the best way to do it, do you know another way to do the same? thanks! – saman0suke Mar 10 '14 at 20:53
  • 1
    Put it in onDetach or onDestroyView, just do an @Override one of those. – Nathaniel D. Waggoner Mar 10 '14 at 20:55
  • Excellent! thanks! one more and I'm done with this...I lose the focus on the selected tab everytime that I change the orientation, it goes back to the first one, what might be the issue? thanks! – saman0suke Mar 10 '14 at 20:58
  • 1
    You will need to call actionBar.selectTab(mainTab); in your activities life cycle - you could override onOrientationChange or some other life cycle method. THere are some intricaces to the fragment lifecycle that you're going to want to be careful of... namely with the way fragments hang around in memory. – Nathaniel D. Waggoner Mar 10 '14 at 21:00
  • I still get the NPE error if I use onDetach or onDestroyView, the application works fine if I use none of them, but I'd like to know why this is happening, besides, I'd like to make sure to close the Cursor and DB. Thanks! – saman0suke Mar 10 '14 at 22:58
  • I would manage the DB outside of the fragments personally. Not sure what might be going on there - the activity might be null or any of a number of other weird things. – Nathaniel D. Waggoner Mar 11 '14 at 00:16