How do I access an Arraylist of Fragments after a screen rotation?

Asked

Viewed 308 times

2

I was trying to programmatically add to my Activity a list of Fragments that implement some Cardviews. These Cardviews have some Textviews that I would like to set from my Activity, and in fact, it works by defining them in events after Fragment onCreateView, such as onStart and onResume. Or rather, no... it’s better to say, it almost works. When there is a screen rotation (and all that would force the restart of an Activity), trying to do something with any Fragment, even in onStart and onRestart methods, results in a Nullpointerexception. Basically I have:

Myactivity.java

private List<MyFragment> cards = new ArrayList<>();

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

    // Check that the activity is using the layout version with
    // the fragment_container FrameLayout
    if (findViewById(R.id.fragment_container) != null) {

        FragmentTransaction transaction = getFragmentManager().beginTransaction();

        // However, if we're being restored from a previous state,
        // then we don't need to do anything and should return or else
        // we could end up with overlapping fragments.

        if (savedInstanceState != null) {
            return;
        }

        /* Here I create 10 fragment cards */
        for(int i = 0; i < 10; i++) {
            cards.add(new MyFragment());
            transaction.add(R.id.fragment_container, cards.get(i));
        }

        transaction.commit();

   }

}

After a few tests, I assumed the problem was in if (savedInstanceState != null) { return; }. I tried those "solutions" that didn’t help me: https://stackoverflow.com/questions/26389938/nullpointerexception-when-accessing-a-fragments-textview-in-an-activity , https://stackoverflow.com/questions/27748277/npe-thrown-when-trying-to-find-button-id-in-android-fragment , https://stackoverflow.com/questions/18534804/how-would-i-implement-a-generic-arraylist-of-fragments-in-android and much more...


Logcat:

01-24 09:07:21.848  30751-30751/io.github.mths0x5f.guiaufu E/IMGSRV﹕ :0: PVRDRMOpen: TP3, ret = 43
01-24 09:07:21.878  30751-30751/io.github.mths0x5f.guiaufu E/IMGSRV﹕ :0: PVRDRMOpen: TP3, ret = 46
01-24 09:07:21.878  30751-30751/io.github.mths0x5f.guiaufu E/IMGSRV﹕ :0: PVRDRMOpen: TP3, ret = 47
01-24 09:07:21.878  30751-30751/io.github.mths0x5f.guiaufu E/IMGSRV﹕ :0: PVRDRMOpen: TP3, ret = 47
01-24 09:07:21.878  30751-30751/io.github.mths0x5f.guiaufu E/IMGSRV﹕ :0: PVRDRMOpen: TP3, ret = 47
01-24 09:07:21.888  30751-30751/io.github.mths0x5f.guiaufu E/IMGSRV﹕ :0: PVRDRMOpen: TP3, ret = 48
01-24 09:07:40.088  30751-30751/io.github.mths0x5f.guiaufu E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: io.github.mths0x5f.guiaufu, PID: 30751
    java.lang.NullPointerException
            at io.github.mths0x5f.guiaufu.ru.MyActivity$2.run(MyActivity.java:161)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5102)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:803)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:619)
            at dalvik.system.NativeStart.main(Native Method)

Code that works on application startup but not after a configuration change:

@Override
protected void onStart() {
    super.onStart();
    ((TextView) cards.get(0).getView().findViewById(R.id.textView)).setText("Test");
}

2 answers

1

Friend, understand... if the device is turned the activity will be destroyed and recreated. Thus, the context in which you passed to your Fragment points on the activity were destroyed. What to do?

You could use setRetainInstance(true) in your Fragment. In this way your Fragment will survive the recreation of Activity :)

To solve the NPE you have to pass the Context in the Fragment, if the activity is recreated. Then Context will belong to the new activity.

Summarizing, without this update to each line of code, which points out about the activity as getActivity() or getFragmentManager(), will lead in a NPE.

If you do not want to use the normal process of destruir-e-recriar, you can use android: configChanges attributes in AndroidManifest.xml.

EXAMPLE:

<activity
    android:name=".SmsPopupActivity"
    android:theme="@android:style/Theme.Dialog"
    android:launchMode="singleTask"
    android:configChanges="orientation|keyboardHidden"
    android:taskAffinity="net.everythingandroid.smspopup.popup">
</activity>

This way it will not be closed when spinning, because onCreate() não é chamado.


Sources:

https://stackoverflow.com/questions/17867184/android-nullpointerexception-in-dialog-when-rotating

http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance%28boolean%29

Study:

http://www.devx.com/wireless/Article/40792/0/page/5

https://stackoverflow.com/questions/456211/activity-restart-on-rotation-android

  • This is a correct answer and @Matheus WITHDREW AS CORRECT for futile reasons.

0


As no answer helped me, I say my solution: I managed to get around the problems by creating a fragment just to store data, according to this "cake recipe" from the documentation itself http://developer.android.com/guide/topics/resources/runtime-changes.html, (that uses setRetainInstance(true) not to lose the instances of the objects declared within Fragment), and using the Bundle saved by Activity. I preferred not to touch . xml because with it I would have to manipulate certain events myself.

With a standard condition I check if the Activity is being recreated. If it is I look for the Data Fragment and get the unmodified objects.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.