2012-04-12 32 views
30

我正在弄清楚什麼是處理屏幕旋轉的最佳方式。我在這裏讀了數百個問題/答案,但我很困惑。在不丟失數據的情況下處理屏幕旋轉 - Android

如何在重新創建活動之前保存myClass數據,以便我可以保留所有重繪活動而無需另一次無用的初始化?

有沒有一種更清潔,更好的方式比parcelable?

我需要處理旋轉,因爲我想更改橫向模式下的佈局。

public class MtgoLifecounterActivity extends Activity { 

    MyClass myClass; 

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

     If (?? first run...myClass == null ?) { 
      myClass = new MyClass(); 
     } else { 
      // do other stuff but I need myClass istance with all values. 
     } 
     // I want that this is called only first time. 
     // then in case of rotation of screen, i want to restore the other instance of myClass which 
     // is full of data. 
    } 
+0

使用'onConfigurationChanged'的東西,請參閱:http://stackoverflow.com/questions/456211/activity-restart-on-rotation-android – Nanne 2012-04-12 15:33:49

回答

21

可以使用覆蓋方法onSaveInstanceState()onRestoreInstanceState()。 或停止對屏幕旋轉呼籲onCreate()剛加入這一行你的清單XML android:configChanges="keyboardHidden|orientation"

注:您的自定義類必須實現以下Parcelable例子。

@Override 
    public void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 
     outState.putParcelable("obj", myClass); 
    } 

@Override 
protected void onRestoreInstanceState(Bundle savedInstanceState) { 
// TODO Auto-generated method stub 
super.onRestoreInstanceState(savedInstanceState); 
myClass=savedInstanceState.getParcelable("obj")); 
} 

public class MyParcelable implements Parcelable { 
    private int mData; 

public int describeContents() { 
    return 0; 
} 

/** save object in parcel */ 
public void writeToParcel(Parcel out, int flags) { 
    out.writeInt(mData); 
} 

public static final Parcelable.Creator<MyParcelable> CREATOR 
     = new Parcelable.Creator<MyParcelable>() { 
    public MyParcelable createFromParcel(Parcel in) { 
     return new MyParcelable(in); 
    } 

    public MyParcelable[] newArray(int size) { 
     return new MyParcelable[size]; 
    } 
}; 

/** recreate object from parcel */ 
private MyParcelable(Parcel in) { 
    mData = in.readInt(); 
} 


} 
+0

但我需要做什麼onSaveInstanceState和onRestoreInstanceState?實現可發佈的內容? – 2012-04-12 15:42:48

+0

是需要實現parcelable。 – 2012-04-12 15:51:02

+0

pffff不存在任何方法+容易?我需要parce我的課InstantAutoComplete從AutoCompleteTextView延伸從EditText延伸實現Filter.FilterListener ....我失去了1天得到所有值.... – delive 2015-12-16 11:15:24

1

如果你沒有必要爲您的活動將剛剛重啓,設置configChanges上在AndroidManifest.xml您的活動屬性是:

android:configChanges="keyboard|keyboardHidden|orientation" 

這將告訴OS,你將負責處理輪換,並且不會重新開始您的活動。使用這種方法將消除您必須保存任何種類的狀態的需要。

+0

這不是的情況下,谷歌開發的勸告反對這種因爲這是假定取向變化是活動可能被處置和重新創建的唯一原因,事實上還有其他一些原因可能會導致這種情況發生。 – BenjaminPaul 2014-05-02 12:10:51

2

對此有兩種(好的)方法。讓您的課程實現Parcelable並將其放入一個包中,或者,如果它更復雜(例如AsyncTask),則返回onRetainNonConfigurationInstance()

然後還有一種懶惰的方式,您只需停止對配置更改作出反應。

+0

這似乎已被棄用!是的,這是相當複雜的對象 - onRetainNonConfigurationInstance() – 2012-04-12 15:41:11

+0

是的,他們不贊成'onRetainNonConfigurationInstance()',但沒有提供替代品,據我所知。 – dmon 2012-04-12 15:43:18

+0

@dmon可以使用一個沒有UI的片段作爲替代:https://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean) – 2017-01-28 16:15:44

27

清單中的活動代碼,你應該有提

<activity 
     android:name="com.example.ListActivity" 
     android:label="@string/app_name" 
     android:configChanges="keyboardHidden|orientation"> 

如果您使用的是Android 2.3(API等級13)及以上使用

<activity 
     android:name="com.example.Activity" 
     android:label="@string/app_name" 
     android:configChanges="keyboardHidden|orientation|screenSize"> 

它應該有工作。

它將與活動標籤,而不是與應用標籤只工作

+2

我的問題是screenSize屬性,謝謝Prashant – bebosh 2015-01-09 02:06:48

+1

隨時歡迎:)... @bebosh – Cool7 2015-01-12 17:11:57

11

可能這已經只是爲新的成員誰粘貼了一個小更新解決了,只是看看Google Developer Site ,從API等級13,你只需要添加此代碼的體現:

<activity android:name=".SplashScreensActivity" 
      android:configChanges="orientation|keyboardHidden|screenSize" 
      android:label="@string/app_name"> 

當這些配置中的一種改變,SplashScreensActivity不會重新啓動。相反,SplashScreensActivity接收對onConfigurationChanged()的調用。此方法傳遞一個Configuration對象,該對象指定新的設備配置。通過閱讀配置中的字段,您可以確定新的配置並通過更新界面中使用的資源進行適當的更改。在調用此方法時,您的活動的Resources對象將更新爲基於新配置返回資源,因此您可以輕鬆地重置UI的元素,而無需系統重新啓動活動。

1

這裏的問題是,你正在失去應用程序的「狀態」。在OOP中,什麼是國家?變量!究竟!因此,當你失去你的變量的數據。

現在,你可以做什麼,找出失去狀態的變量。

enter image description here

當你旋轉你的設備,你現在的活動被完全破壞,即經過的onSaveInstanceState()onPause() onStop() onDestroy()和新的活動是完全建立它通過onCreate() onStart()onRestoreInstanceState去。

粗體兩種方法,onSaveInstanceState()保存當前活動的實例將被銷燬。 onRestoreInstanceState此方法恢復以前活動的保存狀態。這樣你就不會失去以前的應用程序狀態。

以下是您如何使用這些方法。

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

     outState.putString("theWord", theWord); // Saving the Variable theWord 
     outState.putStringArrayList("fiveDefns", fiveDefns); // Saving the ArrayList fiveDefns 
    } 

    @Override 
    public void onRestoreInstanceState(Bundle savedInstanceState, PersistableBundle persistentState) { 
     super.onRestoreInstanceState(savedInstanceState, persistentState); 

     theWord = savedInstanceState.getString("theWord"); // Restoring theWord 
     fiveDefns = savedInstanceState.getStringArrayList("fiveDefns"); //Restoring fiveDefns 
    }