71

我有一个简单的活动,可以在onCreate. 我发现如果我旋转设备,我可以从onCreate再次调用的日志中看到。事实上,因为所有实例变量都再次设置为默认值,所以我知道整个 Activity 已经被重新实例化了。

旋转 2 次后,我得到一个 FC,因为无法为位图分配足够的内存。(活动的所有实例都还在某处吗?还是 GC 清理得不够快?)

@Override
public void onCreate(Bundle savedInstanceState) {
    File externalStorageDir = Environment.getExternalStorageDirectory();
    File picturesDir = new File(externalStorageDir, "DCIM/Camera");
    File[] files = picturesDir.listFiles(new FilenameFilter(){
        public boolean accept(File dir, String name) {
            return name.toLowerCase().endsWith(".jpg");
        }});
    if (files.length > 0) {
        Bitmap bm = BitmapFactory.decodeStream(new FileInputStream(files[0]));
        ImageView view = (ImageView) findViewById(R.id.photo);
        view.setImageBitmap(bm);
    }
}

从我阅读的所有内容来看,onCreate 应该在应用程序的生命周期内调用一次。我错了吗?重新定向设备如何导致重新创建活动?

4

13 回答 13

87
android:configChanges="keyboardHidden|orientation|screenSize"

Caution: Beginning with Android 3.2 (API level 13), the "screen size" also changes when the device switches between portrait and landscape orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher (as declared by the minSdkVersion and targetSdkVersion attributes), you must include the "screenSize" value in addition to the "orientation" value. That is, you must decalare android:configChanges="orientation|screenSize". However, if your application targets API level 12 or lower, then your activity always handles this configuration change itself (this configuration change does not restart your activity, even when running on an Android 3.2 or higher device).

http://developer.android.com/guide/topics/resources/runtime-changes.html

于 2012-09-20T00:46:33.703 回答
57

默认情况下,每次旋转后都会重新创建活动。您可以使用AndroidManifestconfigChanges中标记的属性覆盖此行为。activity有关更多详细信息和不同选项,请参阅http://developer.android.com/guide/topics/resources/runtime-changes.html

于 2011-10-01T06:59:09.883 回答
56

What happen when orientation changed

Life Cycle of orientation

onPause();
onSaveInstanceState();
onStop();
onDestroy();

onCreate();
onStart();
onResume();

---- app recreated and now is running ---

If you do long operation in onCreate() and want prevent re-create your activity add configChanges attribute in your mainfest

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

screenSize if you targeting api >= 13

于 2015-03-04T11:27:12.767 回答
24

Actvity Lifecycle when you rotate screen

onPause
onSaveInstanceState
onStop
onDestroy

onCreate
onStart
onRestoreInstanceState
onResume
于 2017-06-13T02:51:20.903 回答
13

If you want to prevent FC from not enough memory, you need to deallocate resources in onStop() or onPause(). this allows you to use fresh memory in onCreate().

This is an alternate solution to preventing the recreation of the activity by using

android:configChanges="keyboardHidden|orientation"

As sometimes your activity's layout is different in portrait and landscape (layout, layout-land). preventing recreate on orientation change will prevent your activity from using the other orientation's layout.

于 2011-11-02T15:35:24.360 回答
11

是的,onCreate()每次orientation更改时都会调用活动,但您可以通过在活动标签中的文件re-creationActivity添加configChanges attribute来避免活动。ActivityAndroidManifest

android:configChanges="keyboardHidden|orientation"
于 2011-10-01T06:59:36.060 回答
11

On Create method will call everytime when you do orientation, to avoid this you have to use

//Define Below in you Manifest file.
           <activity
                  android:name="com.ecordia.activities.evidence.MediaAttachmentView"
                  android:configChanges="keyboardHidden|orientation|screenSize"
            </activity>

//Define Below in your activity. 

         @Override
            public void onConfigurationChanged(Configuration newConfig) {

              super.onConfigurationChanged(newConfig);

              if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
                  //your code
              } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            //your code

              }
            }

It will works like a charm!!

于 2013-05-07T09:26:33.517 回答
8
于 2011-10-01T07:39:37.763 回答
6

One of the most common and suggested “solutions” to dealing with orientation changes is to not deal with them. You can do this by setting the android:configChanges flag on your Activity in AndroidManifest.xml as shown below:

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

This is NOT the correct way to deal with orientation changes.

CORRECT way is to implement the onSaveInstanceState method (this could be in your Activity, Fragment or both) and place the values you need to save in the Bundle argument that gets passed to the method.

It is nicely described here: http://code.hootsuite.com/orientation-changes-on-android/

While it may seem a bit tedious to implement, handling orientation changes properly provides you with several benefits: you will be able to easily use alternate layouts in portrait and landscape orientations, and you will be able to handle many exceptional states such as low memory situations and interruptions from incoming phone calls without any extra code.

于 2016-08-31T10:04:42.260 回答
3

While the Manifest way may work, there is a better and proper solution for these types of problems. The ViewModel class. You should have a look here: https://developer.android.com/topic/libraries/architecture/viewmodel

Basically, you extend the ViewModel class and define all the data members in it which we want to be unchanged over re creation of the activity (in this case orientation change). And provide relevant methods to access those from the Activity class. So when the Activity is re created, the ViewModel object is still there, and so are our data!

于 2019-09-17T10:04:42.423 回答
2

Kindly see my way of doing it:-

http://animeshrivastava.blogspot.in/2017/08/activity-lifecycle-oncreate-beating_3.html

snippet is:-

@Override
protected void onSaveInstanceState(Bundle b) {
    super.onSaveInstanceState(b);
    String str="Screen Change="+String.valueOf(screenChange)+"....";
    Toast.makeText(ctx,str+"You are changing orientation...",Toast.LENGTH_SHORT).show();
    screenChange=true;
}

@Override
public void onCreate(Bundle b) {
    super.onCreate(b);
    ctx=getApplicationContext();
    if(!screenChange) {
         String str="Screen Change="+String.valueOf(screenChange);
         // ...
    }
}
于 2017-08-03T17:16:36.273 回答
-2

I had the same problem, in which my onCreate is called multiple times when the screen orientation is changed. My problem got solved when i add android:configChanges="orientation|keyboardHidden|screenSize" in the activity tag in manifest

于 2016-07-28T12:23:29.167 回答
-3

I had the same problem and I did some workaround

Define didLoad boolean variable with false value

private boolean didLoad = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity);

    if (!this.didLoad){
        // Your code...
        this.didLoad = true;
    }
于 2016-06-28T09:48:03.873 回答