Android入门——Activity生命周期和横竖屏切换总结

引言

记得当初面试的遇到两个题目:写出横屏切换竖屏Activity的生命周期和A跳转到B的完整生命周期。当时凭着自己的理解答了,于是乎CTO微微一笑:我不评论对错,你有时间自己去运行验证验证……直到最近自己在项目中又遇到了,困扰了蛮久才发现原因,便想总结下(在版本Android 6.0的基础上),毕竟好记性不如烂笔头,何况我的记忆力已经大不如前啦。

Activity完整生命周期

  • onCreate(Bundle savedInstanceState):创建activity时调用。Bundle中可以提出用于创建该 Activity 所需的信息。
  • onStart():activity变为在屏幕上对用户可见时,即获得焦点时,会调用,Activity处于栈顶时
  • onResume():activity开始与用户交互时调用(无论是启动还是重新启动一个活动,该方法总是被调用的)。
  • onPause():activity被暂停或收回cpu和其他资源时调用,activity未被完全遮盖时,该方法用于保存活动状态的。。
  • onStop():activity被停止并转为不可见阶段及后续的生命周期事件时,即失去焦点时调用。
  • onRestart():重新启动activity时调用。该活动仍在栈中,而不是启动新的活动。
    • onDestroy():activity被完全从系统内存中移除时调用,该方法被调用可能是因为有人直接调用 finish()方法 或者系统决定停止该活动以释放资源

一、Activity 的跳转生命周期不受android:configChanges 和 android:lunchMode 影响

例:MainActivity 跳转至 ToActivity,再从ToActivity跳转至MainActivity的完整生命周期,首先看看标准模式下

1、配置了android:configChanges=”orientation|screenSize”

首先新建MainActivity,

onCreate()——>onStart()——>onResume()——>

这里写图片描述
跳转至 ToActivity(跳转可以分为两个步骤,第一个步骤先隐藏MainActivity,再创建ToActivity),

MainActivity的onPause()——>ToActivity的onCreate()——>
ToActivity的onRestart()——>ToActivity的onResume()——>
MainActivity的onSaveInstanceState()——>MainActivity的onStop()——>


从ToActivity跳转回MainActivity,

ToActivity的onPause()——>MainActivity的onCreate()——>
MainActivity的onRestart()——>MainActivity的onResume()——>
ToActivity的onSaveInstanceState()——>ToActivity的onStop()——>


从ToActivity按返回键返回MainActivity(与跳转不同的是返回是会把ToActivity finish掉),

ToActivity的onPause()——>MainActivity的onCreate()——>
MainActivity的onRestart()——>MainActivity的onResume()——>
ToActivity的onSaveInstanceState()——>ToActivity的onStop()——>
ToActivity的onDestory()

这里写图片描述
在MainActivity锁屏时(按Home键也是一样),

onPause()——>onSaveInstanceState()——>onStop()

这里写图片描述
解锁返回到MainActivity

onRestart()——>onStart()——>onResume()

这里写图片描述
经验证Activity跳转时的生命周期变化,与android:configChangesandroid:lunchMode的取值无关(由于篇幅问题截图不一一贴出)。

2、在Activity 里未配置android:configChanges=”orientation|screenSize”

第一次新建MainActivity

跳转至 ToActivity
这里写图片描述
从ToActivity跳转回MainActivity
这里写图片描述
从ToActivity按返回键返回MainActivity
这里写图片描述
在MainActivity锁屏时(按Home键也是一样)
这里写图片描述
解锁返回到MainActivity
这里写图片描述

二、横竖屏切换与Activity的生命周期

onConfigurationChanged事件是在改变屏幕方向、弹出软件盘和隐藏软键盘时,不再去重新触发Activity的onCreate()方法,而是直接执行onConfigurationChanged()方法;有些情况下,当横、竖屏转换时,程序会报错或异常终止,往往是由于重新触发了Activity的生命周期方法。进而造成重复的初始化工作,影响程序效率等等。所以我们合理地在代码中捕获相关事件并进行逻辑处理提高我们的程序的健壮性和高效性。

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            Toast.makeText(MainActivity.this, "现在是竖屏", Toast.LENGTH_SHORT).show();
            Log.d(TAG, "竖屏"+"onConfigurationChanged by MainActivity");
        }
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            Toast.makeText(MainActivity.this, "现在是横屏", Toast.LENGTH_SHORT).show();
            Log.d(TAG, "横屏"+"onConfigurationChanged by MainActivity");
        }
    }

1、配置了Activity节点下的android:configChanges=”orientation|screenSize”

在MainActivity 由竖屏切换为横屏时
这里写图片描述
在MainActivity 由横屏切换为竖屏时
这里写图片描述
在低版本中想捕获横竖屏切换的事件,得先申请权限( Android:name=”android.permission.CHANGE_CONFIGURATION”)
在高版本里直接在清单文件里配置orientation即可,需要注意的是从Android 3.2(API 13)起,ScreenSize也随着设备的横竖切换而改变。
所以,在AndroidManifest.xml里设置的MiniSdkVersion和 TargetSdkVersion属性大于等于13的情况下,如果你想阻止程序在运行时重新加载Activity,除了设置”orientation”,你还必须设置”ScreenSize”,否则还是无法在onConfigurationChanged里捕捉到相应事件。

2、未配置Activity节点下的android:configChanges属性

在MainActivity 由竖屏切换为横屏时

onPause()——>onSaveInstanceState()——>onStop()——> onDestory()——>onCreate()——>onStart()——> onRestoreInstanceState()——>onResume()

Android入门——Activity生命周期和横竖屏切换总结_第1张图片
在MainActivity 由横屏切换为竖屏时

onPause()——>onSaveInstanceState()——>onStop()——> onDestory()——>onCreate()——>onStart()——> onRestoreInstanceState()——>onResume()

Android入门——Activity生命周期和横竖屏切换总结_第2张图片

3、小结

  1. 不设置Activity的android:configChanges和只设置android:configChanges=”orientation”时,切屏会重新调用各个生命周期。
  2. 设置Activityandroid:configChanges=”orientation|screenSize”的,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法。
  3. 切屏时Activity的生命周期不受lunchMode影响。
  4. 当前Activity产生事件弹出Toast、AlertDialog和PopupWindow的时候不会触发相关生命周期方法。
  5. activity在有“被销毁的可能”时,就会调用onSaveInstanceState方法,给你一个机会去保存activity中的数据,之后横竖屏切换时activity确实在“未经你许可的情况下被销毁了”,所以系统又会调用onRestoreInstanceState方法,让你把之前保存的数据恢复

    三、横竖屏切换及其对应布局加载

1、横竖屏动态切换连带横竖屏布局

假如软件在横竖屏之间切换,由于横竖屏的高宽会发生变化,有可能会要求不同的布局。可通过以下两种方法来切换布局:

1.1、在res目录下建立对应的资源文件

在res目录下建立layout-land和layout-port目录,相应的layout文件名不变,比如:layout-land是横屏的layout,layout-port是竖屏的layout,其他的不用管,横竖屏切换时程序调用Activity的onCreate方法中的setOnContent(xxx),系统会自动加载相应的布局。

1.2、通过java代码来判断当前是横屏还是竖屏然后来加载相应的xml布局文件

因为当屏幕变为横屏的时候,系统会重新加载当前Activity的onCreate方法(如果不设置Activity的android:configChanges属性的话),可以把代码判断屏幕方向,再设置调入不同的layout。

/** 1:竖屏 2:横屏 判断屏幕以旋转的方向 */
private int orientation;
orientation=getResources().getConfiguration().orientation;

2、强制设定屏幕的横、竖屏方向

2.1、在清单文件里设置Activity 的android:screenOrientation

//横屏显示设置
android:screenOrientation="lanscape"
//竖屏显示设置
android:screenOrientation="portrait"

2.2 代码调用setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)

在没有配置android:configChanges时,android屏幕的切换会重启Activity,所以在Activity销毁前保存当前活动的状态,并在Activity再次Create的时候载入配置

3、自适应切换屏幕

1、首先,在清单文件对应的Activity下配置

android:screenOrientation="sensor" android:configChanges="orientation|screenSize|keyboardHidden"

2、接着,取得屏幕的长和宽,比较设置横竖屏的变量

Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
if (width > height) {
    orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; // 横屏
} else {
    orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; // 竖屏
}

3、最后,在onConfigurationChanged()函数中追加this.setRequestedOrientation(orientation)

@Override
public void onConfigurationChanged(Configuration newConfig) {  
     super.onConfigurationChanged(newConfig);  
     this.setRequestedOrientation(orientation);  
 }

但是这样的话你切到别的画面的时再返回到原画面,它仍然是横的或竖的。怎么让它从别的屏幕回来后,又重新横竖屏布局呢?
只要在onResume()中在设定下就行了(但是这个仅仅只是支持横竖屏只有一个layout的)

@Override
protected void onResume() {
    orientation = ActivityInfo.SCREEN_ORIENTATION_USER;
    this.setRequestedOrientation(orientation);
    Display display = getWindowManager().getDefaultDisplay();
    int width = display.getWidth();
    int height = display.getHeight();
    if (width > height) {
        orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
    } else {
        orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
    }
    super.onResume();
}

你可能感兴趣的:(android,生命周期,Activity,横竖屏切换,屏幕自适应)