Cannot communicate with Fragment correctly after orientation change

450 views Asked by At

I am having some trouble figuring out the proper way to communicate between fragments when using a FragmentPagerAdapter.

For some context I have an Activity that uses the FragmentPagerAdapter to host two fragments. Fragment A has a button and when pressed it changes text in Fragment B.

Everything works as expected except when I press the button after an orientation change, I get a null pointer exception on the EditText I am changing in Fragment B. After days of debugging it looks like when I call the method in Fragment B that changes the text that it is maybe an old instance of the Fragment.

Here's the code:

The FragmentPagerAdapter which is an inner class in my Activity:

public class MyPagerAdapter extends FragmentPagerAdapter {

    public MyPagerAdapter (FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int i) {
        switch (i) {
            case 0:
                return fragmentA;
            case 1:
                return fragmentB;
        }
        return null;
    }

    @Override
    public int getCount() {
        return tabs.length;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return tabs[position];
    }
}

The Fragments get instantiated in the Activities onCreate method as follows:

FragmentA fragmentA; //Declared outside of onCreate
FragmentB fragmentB; //Declared outside of onCreate

fragmentA = FragmentA.newInstance();
fragmentB = FragmentB.newInstance();

In the Fragment that I press the button I set up an interface as follows:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        testTextInterface = (TestTextInterface) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement testTextInterface");
    }
}

Then when I press the button I have an OnClickListener that fires the following code:

testTextInterface.onTextChanged("Some test text");

Which in turn calls the following method in the Activity:

@Override
public void onTextChanged(String testText) {
    fragmentB.updateText(testText); 

}

And then finally that method in FragmentB:

private void updateText(String incomingText){
    myEditText.setText(incomingText);
}

And that's it, this works perfectly well until I rotate the device causing the Activity to be recreated. Then when I press the button the myEditText view is null in FragmentB in the updateText method.

I've been trying to figure out why for 2 days so I was wondering if anyone can spot where I am going wrong or point me in the right direction as to where I might mind out what is causing the issue?

2

There are 2 answers

0
Qianqian On

I agree with Bruce, but if you do need to keep a reference to the fragment in the activity, you can do something like this:

In you activity, implement a method, let's say 'setFragmentInstance'.

In your fragment, override the onActivityCreated method, in which you can either cast the activity to your activity (if the fragment always stay in that activity) and call that setFragmentInstance method, or you can also add a interface in the fragment, implement it activity and calls the interface's method in onActivityCreated to set the fragment instance.

I asked one similar questions before, but soon after that I got clear about it, see DialogFragment members becomes null after screen rotation

2
Bruce On

The problem is that when you rotate, Android creates new instances of your fragments for you, but you are not getting references to those new instances. It would be safer to not keep references to the fragments in your activity, but rather use findFragmentByTag when you need to.

@Override
public void onTextChanged(String testText) {
    Fragment fragmentB = getFragmentManager().findFragmentByTag("FragmentB");
    fragmentB.updateText(testText);
}

And, of course, make sure to set the fragment's tag either in XML or in code.