2012-04-12 52 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 
    }