23

I have a "hello world"-ish sample app that uses the android-support-v4 fragments API. The activity consists of a button, clicking it will show a DialogFragment. However, configuration changes like rotation cause the dialog to vanish, even if setRetainInstance(true) is used.

Any idea how to fix this?

RetFragment.java

package me.local.HelloFroyo;

import android.os.Bundle;
import android.support.v4.app.*;
import android.util.Log;
import android.view.*;

public class RetFragment extends DialogFragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.hello_dialog_fragment, container);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("RET", "onDestroy");
    }
}

MainActivity.java

package me.local.HelloFroyo;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;

public class MainActivity extends FragmentActivity {

    private static final String TAG_DLG = "myFragDlg";

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.activity_main);
    }

    public void onShowClick(View v) {
        RetFragment ret = new RetFragment();
        ret.show(getSupportFragmentManager(), TAG_DLG);
    }
}
user1324237
  • 273
  • 1
  • 2
  • 7

4 Answers4

32

Just to comment on this:

"even if setRetainInstance(true) is used."

It's not "even if", it's "because of it." If setRetainInstance is false, the dialog is rotated just fine.

This is the work around I found here, which works fine for me: http://code.google.com/p/android/issues/detail?id=17423

@Override
public void onDestroyView()
{
    Dialog dialog = getDialog();

    // Work around bug: http://code.google.com/p/android/issues/detail?id=17423
    if ((dialog != null) && getRetainInstance())
        dialog.setDismissMessage(null);

    super.onDestroyView();
}
Tom anMoney
  • 1,231
  • 1
  • 14
  • 29
  • @ch3rryc0ke did you find any solution to this, I have the same problem. I have implemented the code above but the dialog still gets dismissed – drisse Nov 04 '14 at 12:59
  • I'm not sure about the workaround here, but you're right that you shouldn't use `setRetainInstance` in this case. If there's state you want to persist, use the `savedInstanceState` or `arguments` `Bundle`. There's a [good example](http://developer.android.com/reference/android/app/DialogFragment.html#AlertDialog) in the Android docs about how best to use `DialogFragment` to generate `AlertDialog`s. – jsadler Dec 18 '14 at 20:08
  • 2
    Based on this: http://stackoverflow.com/a/11318942/1041533 I'd say if setRetainInstance is set to true the entire fragment's state is maintained (except for it's views - those need to be re-created). So what you say about the entire Fragment being recreated BECAUSE setRetainInstance(true) does not seem quite right, but rather the opposite is the case? – AgentKnopf Mar 09 '15 at 12:24
5

DialogFragments survive rotation changes on their own, u dont need to setRetainInstance

However if u set it, this is a reproducable bug with setRetainInstance(true) and DialogFragments

http://code.google.com/p/android/issues/detail?id=17423&q=setRetaininstance&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

just dont setRetainInstance, your dialog will work just fine

However if you have an AsyncTask running along in your DialogFragment and you want to persist it use LoaderManager with AsyncTaskLoader.. it also survives configuration changes

AndroidGecko
  • 14,034
  • 3
  • 35
  • 49
1

For those who have problems even after setRetainInstance(true) or overwrite onDestroyView and still doesn't work, make sure you call the super.onSaveInstanceState() when you overwrite onSaveInstanceState:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState); // <-- must call this if you want to retain dialogFragment upon rotation
    ...
}

The dialogFragment should handle the dialog recreation itself upon rotation even without setRetainInstance or overwriting onDestroyView.

Neoh
  • 15,906
  • 14
  • 66
  • 78
-13

try to add

android:configChanges="orientation"

in AndroidManifest file againt your activity.

Drup Desai
  • 995
  • 7
  • 2
  • 1
    I do not want to prevent the whole activity from being destroyed and recreated, I just want to keep the DialogFragment. – user1324237 Jul 03 '12 at 09:23
  • This will not create your activity again. it will remain in the same state if you add this to your activity. Without this statement your activity is creating every time ones you change your orientation. – Drup Desai Jul 03 '12 at 09:33
  • I know, but I only want to retain the _dialog fragment_. The activity is supposed to be destroyed and recreated. Are you familiar with the fragment API? – user1324237 Jul 03 '12 at 09:47
  • I just noticed that the documentation mentions setRetainInstance(true) only works with fragments not on the back stack. I added getFragmentManager.popBackStack() in front of setRetainInstance(true), and now it does work. – user1324237 Jul 03 '12 at 09:57
  • Correction: that did not work properly after all. :( In fact the fragment is still destroyed and recreated, but the dialog is shown after rotation. However, this is not 100% what I need. The dialog instance is supposed to be retained. – user1324237 Jul 03 '12 at 10:05
  • There are other configuration changes besides orientation changes which an app needs to deal with it. Dealing with the most common change and ignoring the others is just an incomplete hack. – sstn Mar 01 '13 at 13:39