Question

I have an Activity that is largely unmodified form the default Android Studio example for a tabbed activity. Its FragmentPagerAdapter is modified to display all 50 United States, with 50 corresponding tabs displaying their names. This works until a fragment is destroyed, but when it's re-created, it's not told which tab it's on. Why does this happen?

The following are all the methods that I think could be part of the problem:

public class MainQuizActivity extends Activity implements ActionBar.TabListener {

    ...

    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        ...

        @Override
        public Fragment getItem(int position) {
            // getItem is called to instantiate the fragment for the given page.
            // Return a PlaceholderFragment (defined as a static inner class below).
            return
                questionFragments[position] == null
                    ? questionFragments[position] = QuestionFragment.newInstance(position)
                    : questionFragments[position];
        }

        ...
    }

    ...
}

...

public class QuestionFragment extends Fragment {

    ...

    public static QuestionFragment newInstance(int stateIndex) {
        System.out.println("Creating new instance for state #" + stateIndex);
        QuestionFragment fragment = new QuestionFragment();
        Bundle args = new Bundle();
        args.putInt(States.BUNDLE_KEY, stateIndex);
        fragment.setArguments(args);
        return fragment;
    }

    ...

    @Override
    public View onCreateView(
        LayoutInflater inflater,
        ViewGroup container,
        Bundle savedInstanceState) {
        System.out.println("~onCreateView");
        View rootView = inflater.inflate(
            R.layout.fragment_main_quiz, container, false);

        webView = (WebView)rootView.findViewById(R.id.webView);
        initState(savedInstanceState);

        return rootView;
    }

    private void initState(Bundle args) {
        if (state == null) {
            System.out.println("Bundle: " + args);
            if (args == null)
                args = getArguments();
            System.out.println("Bundle is now: " + args);
            int stateIndex = args.getInt(States.BUNDLE_KEY);
            System.out.println("Gonna be state #" + stateIndex);
            state = States.values()[stateIndex];
            System.out.println("Gonna be " + state);
        }
        else
            System.out.println("State already exists! (yay!)");

        String path = state.getImageURL();
        System.out.println("Opening image at " + path);

        webView.loadUrl(path);
        webView.setBackgroundColor(0x00000000);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        System.out.println("~onCreate");
        super.onCreate(savedInstanceState);
        if (webView == null)
            webView = (WebView)(getActivity().findViewById(R.id.webView));
        System.out.println("onCreate: webView == " + webView);
        System.out.println("onCreate: bundle == " + savedInstanceState);

        if (webView != null
            && savedInstanceState != null)
        initState(savedInstanceState);
    }

    ...

}

I saved this in the bundle with the key States.BUNDLE_KEY (which is "STATE"), but the bundle it's given does not have that key in it the second time. For debugging purposes, I overrode all on* methods that deal with loading and unloading with empty ones like:

@Override public void onResume(){
    System.out.println("~onResume");
    super.onResume();}

Of course, there are also more debugging outputs that I threw in.

I hope this video I recorded helps illustrate the issue: http://youtu.be/cmbR_2rvpX4

The console dump for the video is in this pastebin: http://pastebin.com/rxAP7qda

And, if all this still doesn't help, here's its git: https://github.com/Supuhstar/US-State-Quiz-App


Even after all this, I feel I'm not giving the right information. Please ask for less or more if you think this can be put better.

Was it helpful?

Solution

You're not initializing things properly in your QuestionFragment. First of all there's no need to call the initState(savedInstanceState); method in both the onCreate() and onCreateView() callbacks. Call it in onCreateView() and remove entirely the onCreate() method:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    System.out.println("~onCreateView");
    View rootView = inflater.inflate(R.layout.fragment_main_quiz, container, false);

    webView = (WebView)rootView.findViewById(R.id.webView);
    guessSpinner = (Spinner)getActivity().findViewById(R.id.guess_spinner);
    initState();
    initGuesser();
    return rootView;
}

Your initState(savedInstanceState) method is also a bit too complicated for what it should do:

private void initState() {
     Bundle args = getArguments();
     if (args == null) {
        throw new IllegalArgumentException("The arguments should be valid!");
     }
     System.out.println("Bundle is now: " + args);
     int stateIndex = args.getInt(States.BUNDLE_KEY); 
     System.out.println("Gonna be state #" + stateIndex);
     state = States.values()[stateIndex];
     System.out.println("Gonna be " + state);
     String path = state.getImageURL();
     System.out.println("Opening image at " + path);

     webView.loadUrl(path);
     webView.setBackgroundColor(getResources().getColor(R.color.transparent));
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top