it-swarm.com.de

Lebenszyklus des Android-Fragments über Orientierungsänderungen

Verwenden des Kompatibilitätspakets zur Verwendung von Fragmenten mit 2.2.

Nach dem Umcodieren einer Aktivität zur Verwendung von Fragmenten in einer App konnte ich die Orientierungsänderungen/Zustandsverwaltung nicht zum Laufen bringen. Daher habe ich eine kleine Test-App mit einer einzigen FragmentActivity und einem einzelnen Fragment erstellt.

Die Protokolle der Orientierungsänderungen sind seltsam mit mehreren Aufrufen der Fragmente OnCreateView.

Offensichtlich fehlt mir etwas - zum Beispiel, das Fragment zu enträtseln und erneut anzuhängen, anstatt eine neue Instanz zu erstellen. Ich kann jedoch keine Dokumentation sehen, die anzeigt, wo ich falsch liege.

Kann jemand etwas Licht darauf werfen, was ich hier falsch mache, bitte ... Danke

Das Protokoll ist nach Änderungen der Ausrichtung wie folgt.

Initial creation
12-04 11:57:15.808: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:15.945: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:16.081: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null


Orientation Change 1
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:57:39.031: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.167: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null


Orientation Change 2
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.361: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.498: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.498: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null

Hauptaktivität (FragmentAktivität)

public class FragmentTestActivity extends FragmentActivity {
/** Called when the activity is first created. */

private static final String TAG = "FragmentTest.FragmentTestActivity";


FragmentManager mFragmentManager;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Log.d(TAG, "onCreate");

    mFragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

    FragmentOne fragment = new FragmentOne();

    fragmentTransaction.add(R.id.fragment_container, fragment);
    fragmentTransaction.commit();
}

Und das Fragment

public class FragmentOne extends Fragment {

private static final String TAG = "FragmentTest.FragmentOne";

EditText mEditText;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    Log.d(TAG, "OnCreateView");

    View v = inflater.inflate(R.layout.fragmentonelayout, container, false);

    // Retrieve the text editor, and restore the last saved state if needed.
    mEditText = (EditText)v.findViewById(R.id.editText1);

    if (savedInstanceState != null) {

        Log.d(TAG, "OnCreateView->SavedInstanceState not null");

        mEditText.setText(savedInstanceState.getCharSequence("text"));
    }
    else {
        Log.d(TAG,"OnCreateView->SavedInstanceState null");
    }
    return v;
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    Log.d(TAG, "FragmentOne.onSaveInstanceState");

    // Remember the current text, to restore if we later restart.
    outState.putCharSequence("text", mEditText.getText());
}

Manifest

<uses-sdk Android:minSdkVersion="8" />

<application
    Android:icon="@drawable/ic_launcher"
    Android:label="@string/app_name" >
    <activity
        Android:label="@string/app_name"
        Android:name=".activities.FragmentTestActivity" 
        Android:configChanges="orientation">
        <intent-filter >
            <action Android:name="Android.intent.action.MAIN" />

            <category Android:name="Android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
109
MartinS

Sie legen Ihre Fragmente übereinander.

Bei einer Konfigurationsänderung fügt sich das alte Fragment bei der Neuerstellung der neuen Aktivität hinzu. Dies ist meistens ein massiver Schmerz im hinteren Bereich.

Sie können Fehler aufhalten, indem Sie dasselbe Fragment verwenden, anstatt ein neues zu erstellen. Fügen Sie einfach diesen Code hinzu:

if (savedInstanceState == null) {
    // only create fragment if activity is started for the first time
    mFragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

    FragmentOne fragment = new FragmentOne();

    fragmentTransaction.add(R.id.fragment_container, fragment);
    fragmentTransaction.commit();
} else {        
    // do nothing - fragment is recreated automatically
}

Seien Sie jedoch gewarnt: Probleme treten auf, wenn Sie versuchen, auf Aktivitätsansichten innerhalb des Fragments zuzugreifen, da sich die Lebenszyklen leicht ändern. (Das Abrufen von Ansichten von einer übergeordneten Aktivität von einem Fragment ist nicht einfach).

174
Graeme

Um dieses Buch zu zitieren, "um eine konsistente Benutzererfahrung sicherzustellen, behält Android das Fragment-Layout und den zugehörigen Back-Stack bei, wenn eine .__-Aktivität aufgrund einer Konfigurationsänderung neu gestartet wird." (S. 124)

Die Vorgehensweise besteht darin, zunächst zu überprüfen, ob der Fragment-Back-Stack bereits gefüllt ist, und die neue Fragmentinstanz nur dann zu erstellen, wenn dies nicht der Fall ist:

@Override
public void onCreate(Bundle savedInstanceState) {

        ...    

    FragmentOne fragment = (FragmentOne) mFragmentManager.findFragmentById(R.id.fragment_container); 

    if (fragment == null) {
        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.fragment_container, new FragmentOne());
        fragmentTransaction.commit();
    }
}
82
k29

Die onCreate () -Methode Ihrer Aktivität wird nach der Orientierungsänderung aufgerufen, wie Sie gesehen haben. Führen Sie also nicht die FragmentTransaction aus, die das Fragment nach der Orientierungsänderung Ihrer Aktivität hinzufügt.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState==null) {
        //do your stuff
    }
}

Die Fragmente sollten und müssen unverändert bleiben.

9
Αλέκος

Sie können die FragmentActivity mit onSaveInstanceState()@Overrideen. Stellen Sie sicher, dass Sie die super.onSaveInstanceState() in der Methode nicht aufrufen.

4
Victor.Chan

Wir sollten immer versuchen, eine Ausnahme von nullpointer zu verhindern, also müssen wir zuerst die saveinstance-Methode auf Bündelinformationen überprüfen. für eine kurze Erklärung, um diesen Blog zu überprüfen link

public static class DetailsActivity extends Activity {

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

        if (getResources().getConfiguration().orientation
            == Configuration.ORIENTATION_LANDSCAPE) {
            // If the screen is now in landscape mode, we can show the
            // dialog in-line with the list so we don't need this activity.
            finish();
            return;
        }

        if (savedInstanceState == null) {
            // During initial setup, plug in the details fragment.
            DetailsFragment details = new DetailsFragment();
            details.setArguments(getIntent().getExtras());
            getFragmentManager().beginTransaction().add(Android.R.id.content, details).commit();
        }
    } 
}
0
abhi

Bei Konfigurationsänderungen erstellt das Framework für Sie eine neue Instanz des Fragments und fügt es der Aktivität hinzu. Also stattdessen:

FragmentOne fragment = new FragmentOne();

fragmentTransaction.add(R.id.fragment_container, fragment);

mach das:

if (mFragmentManager.findFragmentByTag(FRAG1_TAG) == null) {
    FragmentOne fragment = new FragmentOne();

    fragmentTransaction.add(R.id.fragment_container, fragment, FRAG1_TAG);
}

Beachten Sie, dass das Framework bei Orientierungsänderungen eine neue Instanz von FragmentOne hinzufügt, es sei denn, Sie rufen setRetainInstance (true) auf. In diesem Fall wird die alte Instanz von FragmentOne hinzugefügt.

0
vlazzle