Search code examples
androidandroid-fragmentsandroid-serviceandroid-dialogandroid-dialogfragment

When restoring from an orientation change, DialogFragment onCreateDialog() is called before onServiceConnected()


I have a big problem with my DialogFragments.

My DialogFragments depend on a service connection to function properly. This is OK when the user presses a button to pop open a dialog because the activity draws the button in onServiceConnected(), ensuring that the service is always available to the DialogFragment.

public class GameActivity extends Activity {

  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Start the service.
    Intent gameServiceIntent = new Intent(this, GameService.class);
    startService(gameServiceIntent);
    bindService(gameServiceIntent, mConnection, Context.BIND_AUTO_CREATE);

    ... 

  private ServiceConnection mConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder service) {

      // Assign the gameService object to a member variable.
      GameActivity.this.gameService = ((GameService.LocalBinder)service).getService();

      // Create a button that pops up a dialog.  
      // The dialog uses MainActivity.getGameService().

      ...

  public GameService getGameService() {
    return gameService;
  }

  ...

And then the DialogFragment uses the game service.

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {

  this.gameActivity = (GameActivity) getActivity();
  gameActivity.getService();

On orientation change, however (when the user rotates the phone with the dialog open), when restoring the application state Android calls DialogFragment.onCreateDialog() before it calls onServiceConnected(). Then when the dialog calls MainActivity.getGameService(), I get a null pointer exception and a crash.

This is also a problem for all other UI components that are built in onServiceConnected(). For example, a ListView and a TableLayout. They are null when the Dialog is created because onCreateDialog() is called before onServiceConnected().

How can I fix this?!


Solution

  • Solved a similar problem as follows:

    private Parcelable data;
    
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Parcelable serviceData = myService.getSomeData();
        outState.putParcelable("data", serviceData)
    }
    
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        if (savedInstanceState != null) {
           // create from bundle
           data = savedInstanceState.getParcelable("data");
        } else {
           // create from service
           data = myService.getSomeData();
        }
        ...
    }