ki9
ki9

Reputation: 5575

Starting a fragment calls activity's onCreate()

I have an AppCompatPreference SettingsActivity with a PreferenceFragment, like this:

public class SettingsActivity extends AppCompatPreferenceActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "activity onCreate called");
        setupActionBar();

        String userString = getIntent().getStringExtra(LoginActivity.USER);
        Log.v(TAG, "UserString: " + userString);

        ...
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static class GeneralPreferenceFragment extends PreferenceFragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG, "GeneralPreferenceFragment onCreate called");

            addPreferencesFromResource(R.xml.pref_general);
            setHasOptionsMenu(true);
        }
    }
}

When I start the app, a LoginActivity authenticates with a server and passes user data (userString) to the SettingsActivity. It then starts a service with that data.

Everything is peachy and the service starts with no problem.

D/SettingsActivity: activity onCreate called
V/SettingsActivity: UserString: {some string of JSON user data}

But then I tap on General Preferences. As soon as I do so, this gets logged:

D/SettingsActivity: activity onCreate called
V/SettingsActivity: UserString: null

Because it logs activity onCreate called instead of GeneralPreferenceFragment onCreate called, it seems like the wrong onCreate() is being called. The app then crashes with a NullPointException trying to start the service with a null user.

I am trying to figure this out. Maybe the entire activity is restarting for some reason? Any suggestions on diagnosing this problem would help.

Upvotes: 0

Views: 397

Answers (1)

rds
rds

Reputation: 26984

As your log shows, a new instance of activity is created.

This is the expected behaviour of the PreferenceActivity on a phone. Tablets use a two-pane layout and keep a single activity. But phones start a new activity.

AppCompat behaves the same.

You can however pass more data to the fragment with

public class MySettingsActivity extends PreferenceActivity {
    @Override
    public void onBuildHeaders(List<Header> target) {
        super.onBuildHeaders(target);
        // You can build with xml settings that don't depend from UserString
        loadHeadersFromResource(R.xml.preferences, target);
        // For Settings that depend on UserString:
        Header userHeader = new Header();
        userHeader.title = ""; // TODO
        user.fragment = UserFragment.class;
        Bundle args = new Bundle(1);
        // TODO Pass a User parcelable instead
        args.putString(EXTRA_USER, userString);
        userHeader.fragmentArguments = args;
    }
}

Upvotes: 1

Related Questions