android-activity restore - Aktivität Neustart bei Rotation Android



handle value (25)

Sie müssen die onSavedInstanceState-Methode verwenden, um den gesamten Wert für seinen Parameter zu speichern

@Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        outPersistentState.putBoolean("key",value);
    }

und benutzen

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        savedInstanceState.getBoolean("key");
    } 

Um den Wert zurückzugewinnen und den Wert für die Anzeige von Objekten festzulegen, werden die Bildschirmdrehungen behandelt

Wenn ich in meiner Android-Anwendung das Gerät onCreate (die Tastatur onCreate ), wird meine Activity neu gestartet ( onCreate wird aufgerufen). Nun, das ist wahrscheinlich so, wie es sein sollte, aber ich mache eine Menge von onCreate in der onCreate Methode, also brauche ich entweder:

  1. Legen Sie die Ersteinrichtung in eine andere Funktion, so dass bei der Gerätedrehung nicht alles verloren geht oder
  2. Mach es so onCreate wird nicht noch einmal aufgerufen und das Layout passt gerade an oder
  3. Begrenzen Sie die App auf nur Hochformat, damit onCreate nicht aufgerufen wird.


 onConfigurationChanged is called when the screen rotates. 
 (onCreate is no longer called when screen rotates due to manifest, see:  
 android:configChanges)

Welcher Teil des Manifests sagt, dass " onCreate() " nicht aufgerufen wird?

Auch die Google-Dokumente sagen, dass die Verwendung von android:configChanges (außer als letztes Mittel) zu vermeiden ist .... Aber dann verwenden die alternativen Methoden, die sie vorschlagen, alle android:configChanges .

Es ist meine Erfahrung, dass der Emulator onCreate() bei Rotation aufruft.
Aber die 1-2 Geräte, auf denen ich den gleichen Code laufen lasse ... nicht. (Nicht sicher, warum es einen Unterschied geben würde.)


Die onCreate Methode wird weiterhin aufgerufen, auch wenn Sie die orientation von Android ändern. Es wird Ihnen also nicht helfen, die ganze schwere Funktionalität auf diese Methode zu übertragen


Verwenden Sie den orientation , um verschiedene Aufgaben mit unterschiedlicher Ausrichtung auszuführen.

@Override
public void onConfigurationChanged(Configuration myConfig) 
{
    super.onConfigurationChanged(myConfig);
    int orient = getResources().getConfiguration().orientation; 
    switch(orient) 
    {
       case Configuration.ORIENTATION_LANDSCAPE:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    break;
       case Configuration.ORIENTATION_PORTRAIT:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    break;
       default:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }
}

Sie können auch die Art und Weise des onRetainNonConfigurationInstance() von Daten der Android-Plattform über Orientierungsänderungen hinweg in onRetainNonConfigurationInstance() : onRetainNonConfigurationInstance() und getLastNonConfigurationInstance() .

Auf diese Weise können Sie Daten über Konfigurationsänderungen hinweg beibehalten, z. B. Informationen, die Sie möglicherweise von einem Server-Abruf oder einem anderen in onCreate oder seither berechneten onCreate , während Android Ihre Activity jetzt mithilfe der XML-Datei neu onCreate in Benutzung.

Siehe here oder hier .

Es sollte beachtet werden, dass diese Methoden nun veraltet sind (obwohl sie immer noch flexibler sind als die Orientierungsänderung selbst, wie die meisten der obigen Lösungen nahelegen) mit der Empfehlung, dass jeder zu Fragments und stattdessen setRetainInstance(true) für jedes Fragment du behalten möchtest .


Dazu gibt es mehrere Möglichkeiten:

Aktivitätsstatus speichern

Sie können den Aktivitätsstatus in onSaveInstanceState .

@Override
public void onSaveInstanceState(Bundle outState) {
    /*Save your data to be restored here
    Example : outState.putLong("time_state", time); , time is a long variable*/
    super.onSaveInstanceState(outState);
}

Verwenden Sie dann das bundle , um den Status wiederherzustellen.

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

    if(savedInstanceState!= null){
       /*When rotation occurs
        Example : time = savedInstanceState.getLong("time_state", 0); */
    } else {
      //When onCreate is called for the first time
    }
}

Orientierungsänderungen selbständig handhaben

Eine weitere Alternative besteht darin, die Orientierungsänderungen selbst zu handhaben. Dies wird jedoch nicht als gute Praxis angesehen.

Fügen Sie dies Ihrer Manifestdatei hinzu.

android:configChanges="keyboardHidden|orientation"

für Android 3.2 und höher:

android:configChanges="keyboardHidden|orientation|screenSize"

@Override
public void onConfigurationChanged(Configuration config) {
    super.onConfigurationChanged(config);

if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        //Handle rotation from landscape to portarit mode here
    } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
        //Handle rotation from portrait to landscape mode here
    }
}

Rotation beschränken

Sie können Ihre Aktivität auch auf Hoch- oder Querformat beschränken, um eine Rotation zu vermeiden.

Fügen Sie dies zum Aktivitäts-Tag in Ihrer Manifest-Datei hinzu:

        android:screenOrientation="portrait"

Oder implementieren Sie dies programmatisch in Ihrer Aktivität:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

Hinweis: Ich poste diese Antwort, wenn jemand in der Zukunft das gleiche Problem wie ich habe. Für mich war die folgende Zeile nicht genug:

android:configChanges="orientation"

Wenn ich den Bildschirm gedreht habe, wurde die Methode `onConfigurationChanged (Configuration newConfig) nicht aufgerufen.

Lösung: Ich musste auch "screenSize" hinzufügen, auch wenn das Problem mit der Ausrichtung zu tun hatte. Fügen Sie in der AndroidManifest.xml - Datei Folgendes hinzu:

android:configChanges="keyboardHidden|orientation|screenSize"

Implementiere dann die Methode onConfigurationChanged(Configuration newConfig)


Es ist sehr einfach, nur die folgenden Schritte auszuführen:

<activity
    android:name=".Test"
    android:configChanges="orientation|screenSize"
    android:screenOrientation="landscape" >
</activity>

Das funktioniert für mich:

Hinweis: Die Ausrichtung hängt von Ihrer Anforderung ab


Obwohl es nicht "der Android-Weg" ist, habe ich sehr gute Ergebnisse erzielt, indem ich Orientierungsänderungen selbst gehandhabt habe und die Widgets einfach innerhalb einer Ansicht neu positioniert habe, um die veränderte Ausrichtung zu berücksichtigen. Dies ist schneller als jeder andere Ansatz, da Ihre Ansichten nicht gespeichert und wiederhergestellt werden müssen. Es bietet auch eine nahtlose Erfahrung für den Benutzer, da die neu positionierten Widgets genau dieselben Widgets sind, die nur verschoben und / oder in der Größe verändert wurden. Auf diese Weise kann nicht nur der Modellzustand, sondern auch der Ansichtszustand erhalten werden.

RelativeLayout kann manchmal eine gute Wahl für eine Ansicht sein, die sich von Zeit zu Zeit neu ausrichten muss. Sie stellen lediglich eine Reihe von Layout-Parametern für das Layout und eine Reihe von Landschafts-Layout-Parametern mit jeweils unterschiedlichen relativen Positionierungsregeln für jedes Kind-Widget bereit. Dann übergeben Sie in Ihrer onConfigurationChanged() -Methode die entsprechende an einen setLayoutParams() Aufruf für jedes Kind. Wenn ein untergeordnetes Steuerelement selbst intern neu ausgerichtet werden muss, rufen Sie einfach eine Methode für dieses untergeordnete Element auf, um die Neuausrichtung durchzuführen. Dieses Kind ruft auf ähnliche Weise Methoden für seine untergeordneten Steuerelemente auf, die eine interne Neuausrichtung erfordern, und so weiter.


Fügen Sie diese Zeile android: configChanges = "orientation | screenSize" in Manifest hinzu


Anstatt zu versuchen, onCreate() insgesamt zu stoppen, versuchen Sie vielleicht, das Bundle savedInstanceState zu savedInstanceState , das an das Ereignis übergeben wird, um savedInstanceState , ob es null ist oder nicht.

Wenn ich zum Beispiel eine Logik habe, die ausgeführt werden sollte, wenn die Activity wirklich erstellt wird, und nicht bei jeder Orientierungsänderung, onCreate() ich diese Logik nur in onCreate() , wenn savedInstanceState null ist.

Ansonsten möchte ich, dass das Layout für die Ausrichtung korrekt neu gezeichnet wird.

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_game_list);

        if(savedInstanceState == null){
            setupCloudMessaging();
        }
}

nicht sicher, ob dies die ultimative Antwort ist, aber es funktioniert für mich.


Fügen Sie im Abschnitt "Aktivität" des manifest Folgendes hinzu:

android:configChanges="keyboardHidden|orientation"

Änderungen, die im Android-Manifest vorgenommen werden müssen, sind:

android:configChanges="keyboardHidden|orientation" 

Innerhalb der Aktivität müssen folgende Ergänzungen vorgenommen werden:

public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

Nach einer Weile der Versuch und Irrtum fand ich eine Lösung, die in den meisten Situationen meine Bedürfnisse erfüllt. Hier ist der Code:

Manifestkonfiguration:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.pepperonas.myapplication">

    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

Hauptaktivität:

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "MainActivity";

    private Fragment mFragment;

    private int mSelected = -1;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate  " + "");

        // null check not realy needed - but just in case...
        if (savedInstanceState == null) {

            initUi();

            // get an instance of FragmentTransaction from your Activity
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

            /*IMPORTANT: Do the INITIAL(!) transaction only once!
            * If we call this everytime the layout changes orientation,
            * we will end with a messy, half-working UI.
            * */
            mFragment = FragmentOne.newInstance(mSelected = 0);
            fragmentTransaction.add(R.id.frame, mFragment);
            fragmentTransaction.commit();
        }
    }


    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.d(TAG, "onConfigurationChanged  " +
                   (newConfig.orientation
                    == Configuration.ORIENTATION_LANDSCAPE
                    ? "landscape" : "portrait"));

        initUi();

        Log.i(TAG, "onConfigurationChanged - last selected: " + mSelected);
        makeFragmentTransaction(mSelected);
    }


    /**
     * Called from {@link #onCreate} and {@link #onConfigurationChanged}
     */
    private void initUi() {
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate  instanceState == null / reinitializing..." + "");
        Button btnFragmentOne = (Button) findViewById(R.id.btn_fragment_one);
        Button btnFragmentTwo = (Button) findViewById(R.id.btn_fragment_two);
        btnFragmentOne.setOnClickListener(this);
        btnFragmentTwo.setOnClickListener(this);
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME!!!");
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME, AS WELL!!!");
    }


    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume  " + "");
    }


    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause  " + "");
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy  " + "");
    }


    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.btn_fragment_one:
                Log.d(TAG, "onClick btn_fragment_one " + "");
                makeFragmentTransaction(0);
                break;

            case R.id.btn_fragment_two:
                Log.d(TAG, "onClick btn_fragment_two " + "");
                makeFragmentTransaction(1);
                break;

            default:
                Log.d(TAG, "onClick  null - wtf?!" + "");
        }
    }


    /**
     * We replace the current Fragment with the selected one.
     * Note: It's called from {@link #onConfigurationChanged} as well.
     */
    private void makeFragmentTransaction(int selection) {

        switch (selection) {
            case 0:
                mFragment = FragmentOne.newInstance(mSelected = 0);
                break;
            case 1:
                mFragment = FragmentTwo.newInstance(mSelected = 1);
                break;
        }

        // Create new transaction
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack
        transaction.replace(R.id.frame, mFragment);

        /*This would add the Fragment to the backstack...
        * But right now we comment it out.*/
        //        transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
    }

}

Und Beispielfragment:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * @author Martin Pfeffer (pepperonas)
 */
public class FragmentOne extends Fragment {

    private static final String TAG = "FragmentOne";


    public static Fragment newInstance(int i) {
        Fragment fragment = new FragmentOne();
        Bundle args = new Bundle();
        args.putInt("the_id", i);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView  " + "");
        return inflater.inflate(R.layout.fragment_one, container, false);
    }

}

Kann auf github .


Was ich getan habe...

im Manifest zum Aktivitätsabschnitt hinzugefügt:

android:configChanges="keyboardHidden|orientation"

im Code für die Aktivität implementiert:

//used in onCreate() and onConfigurationChanged() to set up the UI elements
public void InitializeUI()
{
    //get views from ID's
    this.textViewHeaderMainMessage = (TextView) this.findViewById(R.id.TextViewHeaderMainMessage);

    //etc... hook up click listeners, whatever you need from the Views
}

//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    InitializeUI();
}

//this is called when the screen rotates.
// (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
@Override
public void onConfigurationChanged(Configuration newConfig)
{
    super.onConfigurationChanged(newConfig);
    setContentView(R.layout.main);

    InitializeUI();
}

Die Methode, die ich gefunden habe, ist, die onRestoreInstanceState und onSaveInstanceState Ereignisse zu verwenden, um etwas im Bundle zu speichern (auch wenn Sie keine gespeicherten Variablen benötigen, legen Sie einfach etwas hinein, damit das Bundle nicht leer ist). Überprüfen Sie dann bei der onCreate Methode, ob das Bundle leer ist, und wenn dies der onCreate ist, führen Sie die Initialisierung durch, wenn nicht, dann tun Sie es.


Verwenden der Anwendungsklasse

Je nachdem, was Sie bei der Initialisierung tun, können Sie eine neue Klasse erstellen, die Application und den Initialisierungscode in eine überschriebene onCreate Methode innerhalb dieser Klasse verschiebt.

public class MyApplicationClass extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // TODO Put your application initialization code here.
  }
}

Das onCreate in der Anwendungsklasse wird nur aufgerufen, wenn die gesamte Anwendung erstellt wurde. Die Aktivität wird also neu onCreate wenn Änderungen an der Tastatursichtbarkeit nicht ausgelöst werden.

Es empfiehlt sich, die Instanz dieser Klasse als Singleton verfügbar zu machen und die Anwendungsvariablen, die Sie initialisieren, mithilfe von Getter und Setter freizulegen.

HINWEIS: Sie müssen den Namen Ihrer neuen Application-Klasse im Manifest angeben, damit sie registriert und verwendet werden kann:

<application
    android:name="com.you.yourapp.MyApplicationClass"

Reagieren auf Konfigurationsänderungen [UPDATE: Dies ist veraltet seit API 13; siehe die empfohlene Alternative ]

Als weitere Alternative können Sie Ihre Anwendung auf Ereignisse aufmerksam machen lassen, die einen Neustart verursachen - z. B. Ausrichtung und Änderungen der Tastatursichtbarkeit - und diese in Ihrer Aktivität behandeln.

Beginnen Sie, indem Sie den Knoten android:configChanges zum Manifestknoten Ihrer Aktivität hinzufügen

android:configChanges="keyboardHidden|orientation"

oder für Android 3.2 (API Level 13) und neuer :

android:configChanges="keyboardHidden|orientation|screenSize"

onConfigurationChanged dann innerhalb der Aktivität die onConfigurationChanged Methode und rufen Sie setContentView auf, um zu erzwingen, dass das GUI-Layout in der neuen Ausrichtung erneut ausgeführt wird.

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  setContentView(R.layout.myLayout);
}

Jedes Mal, wenn der Bildschirm gedreht wird, ist die geöffnete Aktivität beendet und onCreate () wird erneut aufgerufen.

1. Sie können eine Sache tun, um den Status der Aktivität zu speichern, wenn der Bildschirm gedreht wird, so dass Sie alle alten Sachen wiederherstellen können, wenn die Aktivität onCreate () erneut aufgerufen wird. Siehe this Link

2. Wenn Sie den Neustart der Aktivität verhindern möchten, platzieren Sie einfach die folgenden Zeilen in Ihrer Datei manifest.xml.

  <activity android:name=".Youractivity"
  android:configChanges="orientation|screenSize"/>

Mit diesem Code können Sie die aktuelle Ausrichtung des Bildschirms festlegen ...

int currentOrientation =context.getResources().getConfiguration().orientation;
        if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
            ((Activity) context).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        } else {
            ((Activity) context). setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }

Update für Android 3.2 und höher:

Achtung : Ab Android 3.2 (API Level 13) ändert sich auch die "Bildschirmgröße", wenn das Gerät zwischen Hoch- und Querformat wechselt. Wenn Sie daher bei der Entwicklung für die API-Stufe 13 oder höher (wie von den Attributen minSdkVersion und targetSdkVersion deklariert) Laufzeit-Neustarts aufgrund von Orientierungsänderungen verhindern möchten, müssen Sie den Wert "screenSize" zusätzlich zum Wert für "orientation" "screenSize" . Das heißt, Sie müssen android:configChanges="orientation|screenSize" . Wenn Ihre Anwendung jedoch auf die API-Stufe 12 oder niedriger abzielt, verarbeitet Ihre Aktivität diese Konfigurationsänderung immer selbst (diese Konfigurationsänderung startet Ihre Aktivität nicht neu, selbst wenn sie auf einem Gerät mit Android 3.2 oder höher ausgeführt wird).


Ich habe gerade diese Überlieferung entdeckt:

Um die Aktivität durch eine Orientierungsänderung am Leben zu erhalten und sie über onConfigurationChanged , onConfigurationChanged die Dokumentation und das obige Codebeispiel onConfigurationChanged in der Manifest-Datei vor:

android:configChanges="keyboardHidden|orientation"

Das hat den zusätzlichen Vorteil, dass es immer funktioniert.

Die Bonusüberlieferung ist, dass das Auslassen der keyboardHidden logisch erscheinen mag, aber es verursacht Fehler im Emulator (zumindest für Android 2.1): OnCreate nur die orientation wird, ruft der Emulator manchmal OnCreate und onConfigurationChanged und nur OnCreate andere Male auf.

Ich habe den Fehler auf einem Gerät nicht gesehen, aber ich habe gehört, dass der Emulator für andere versagt hat. Es lohnt sich also, zu dokumentieren.


Was Sie beschreiben, ist das Standardverhalten. Sie müssen diese Ereignisse selbst erkennen und behandeln, indem Sie Folgendes hinzufügen:

android:configChanges

zu Ihrem Manifest und dann die Änderungen, die Sie behandeln möchten. Zur Orientierung würden Sie verwenden:

android:configChanges="orientation"

und für das Öffnen oder Schließen der Tastatur würden Sie verwenden:

android:configChanges="keyboardHidden"

Wenn Sie beides behandeln möchten, können Sie sie einfach mit dem Pipe-Befehl trennen:

android:configChanges="keyboardHidden|orientation"

Dies löst die onConfigurationChanged-Methode in jeder Aktivität aus, die Sie aufrufen. Wenn Sie die Methode überschreiben, können Sie die neuen Werte übergeben.

Hoffe das hilft.



onSaveInstanceStatus wirklich angeben, wenn die Aktivität in den Hintergrund wechselt

Zitat aus den Dokumenten: "Die Methode onSaveInstanceState(Bundle)wird aufgerufen, bevor die Aktivität in einen solchen Hintergrundzustand versetzt wird"





android rotation android-activity