Activity横竖屏切换

Activity的生命周期,这是每个Android开发者必须了解的知识。Activity是四大组件之一,而且是使用最频繁的组件。横竖屏切换是每个Android开发者都会遇到的问题。那么横竖屏切换后Activity到底发生了什么呢?

1、生命周期的变化

建一个Activity,重写所有的生命周期方法,然后在这些方法中添加Log。

public class ActivityA extends Activity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.test_layout);
     Log.i("axe.mg","onCreate()");
   }

   @Override
   protected void onRestart() {
     super.onRestart();
     Log.i("axe.mg","onRestart()");
   }

   @Override
   protected void onStart() {
     super.onStart();
     Log.i("axe.mg","onStart()");
   }

   @Override
   protected void onResume() {
     super.onResume();
     Log.i("axe.mg","onResume()");
   }

   @Override
   protected void onPause() {
     super.onPause();
     Log.i("axe.mg","onPause()");
   }

   @Override
   protected void onStop() {
     super.onStop();
     Log.i("axe.mg","onStop()");
   }

   @Override
   protected void onDestroy() {
     super.onDestroy();
     Log.i("axe.mg","onDestroy()");
   }
}

正常启动这个Activity。

09-28 23:16:49.809 24348-24348/com.mg.axe.androiddevelop I/axe.mg: onCreate()
09-28 23:16:49.809 24348-24348/com.mg.axe.androiddevelop I/axe.mg: onStart()
09-28 23:16:49.819 24348-24348/com.mg.axe.androiddevelop I/axe.mg: onResume()

通过Log可以看到Activity从创建到展示的的生命周期: onCreate() —>onStart() —>onResume()

进行横竖屏切换。

09-28 23:17:42.519 24348-24348/com.mg.axe.androiddevelop I/axe.mg: onPause()
09-28 23:17:42.519 24348-24348/com.mg.axe.androiddevelop I/axe.mg: onStop()
09-28 23:17:42.519 24348-24348/com.mg.axe.androiddevelop I/axe.mg: onDestroy()

09-28 23:17:42.719 24348-24348/com.mg.axe.androiddevelop I/axe.mg: onCreate()
09-28 23:17:42.729 24348-24348/com.mg.axe.androiddevelop I/axe.mg: onStart()
09-28 23:17:42.729 24348-24348/com.mg.axe.androiddevelop I/axe.mg: onResume()

通过Log将生命周期分为两部分来分析:
1、Activity销毁: onPause() —> onStop() —> onDestroy()
2、Activity的重新创建展示 :onCreate() —> onStart() —>onResume()

结论:当Activity横竖屏切换时.Activity就会重新创建。
横竖屏切换时Activity会被销毁 , onPause() onStop() onDestory() 会被调用。
然后Activity又会被重新创建,onCreate() onStart() onResume() 会被调用。

2、横竖屏切换后的数据恢复

已经知道Activity横竖屏切换时Activity会重新创建。那么如何恢复重建前的数据呢?
Activity中有两个方法用来保存和恢复Activity重建前的数据:

  @Override
  protected void onSaveInstanceState(Bundle outState) {
     super.onSaveInstanceState(outState);
  }

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

onSaveInstanceState:横竖屏切换时,Activity销毁前系统会调用onSaveInstanceState通过保存Bundle参数来保存当前的Activity的数据。这个方法会在onStop前调用。

onRestoreInstanceState:当Activity被重新创建之后会调用onRestoreInstanceState,并把Activity销毁时 onSaveInstanceState方法所保留的数据作为Bundle参数同时传递给onRestoreInstanceState和onCreate方法。所以我们可以在onRestoreInstanceState和onCreate方法中看到两个一样的参数Bundle savedInstanceState。这个方法会在onStart后调用。

强调一点:必须是Activity异常情况下被终止(例如:横竖屏切换)才会调用这两个方法。

通过代码验证:在Activity中重写onSaveInstanceState和onRestoreInstanceState来保存和恢复Activity重建前的数据。

在onSaveInstanceState保存一个“value_string”的string
在onRestoreInstanceState获取“value_string”这个值。

public class ActivityA extends Activity {

   @Override
   protected void onSaveInstanceState(Bundle outState) {
     super.onSaveInstanceState(outState);
     outState.putString("key","value_string");
     Log.i("axe.mg","onSaveInstanceState");
   }

   @Override
   protected void onRestoreInstanceState(Bundle savedInstanceState) {
     super.onRestoreInstanceState(savedInstanceState);
     String str =   savedInstanceState.getString("key");
     Log.i("axe.mg","onRestoreInstanceState");Log.i("axe.mg","get value:"+str);
   }

   @Override
   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.test_layout);
     Log.i("axe.mg","onCreate()");
   }

   @Override
   protected void onRestart() {
     super.onRestart();
     Log.i("axe.mg","onRestart");
   }

   @Override
   protected void onStart() {
     super.onStart();
     Log.i("axe.mg","onStart()");
   }

   @Override
   protected void onResume() {
     super.onResume();
     Log.i("axe.mg","onResume()");
   }

   @Override
   protected void onPause() {
     super.onPause();
     Log.i("axe.mg","onPause()");
   }

   @Override
   protected void onStop() {
     super.onStop();
     Log.i("axe.mg","onStop()");
   }

   @Override
   protected void onDestroy() {
     super.onDestroy();
     Log.i("axe.mg","onDestroy()");
   }

横竖屏后获取到的Log。

09-29 00:26:25.439 27568-27568/com.mg.axe.androiddevelop I/axe.mg: onPause()
09-29 00:26:25.439 27568-27568/com.mg.axe.androiddevelop I/axe.mg: onSaveInstanceState
09-29 00:26:25.439 27568-27568/com.mg.axe.androiddevelop I/axe.mg: onStop()
09-29 00:26:25.439 27568-27568/com.mg.axe.androiddevelop I/axe.mg: onDestroy()

09-29 00:26:25.499 27568-27568/com.mg.axe.androiddevelop I/axe.mg: onCreate()
09-29 00:26:25.499 27568-27568/com.mg.axe.androiddevelop I/axe.mg: onStart()
09-29 00:26:25.499 27568-27568/com.mg.axe.androiddevelop I/axe.mg: onRestoreInstanceState
09-29 00:26:25.499 27568-27568/com.mg.axe.androiddevelop I/axe.mg: get value:value_string
09-29 00:26:25.499 27568-27568/com.mg.axe.androiddevelop I/axe.mg: onResume()

通过Log来分析:
1、Activity销毁,调用onSaveInstanceState,在onSaveInstanceState方法里面
通过outState.putString(“key”,”value_string”);保存了“value_string”这个值。

2、Activity重建,调用onRestoreInstanceState,在onSaveInstanceState方法里面
通过savedInstanceState.getString(“key”);获取出了“value_string”这个值。

3、如何防止横竖屏切换时Activity重建

可能在开发中并不希望横竖屏切换后Activity重建。此时需要配置configChange参数,
可以设置: android:configChanges=”orientation|screenSize”

<activity
   android:name=".develop.ActivityA"
   android:label="@string/app_name"
   android:configChanges="orientation|screenSize"
   android:theme="@style/AppTheme.NoActionBar">
     <intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
</activity>

配置添加android:configChanges=”orientation|screenSize”
(跟踪framework层代码,是由于google在android3.2中添加了screensize改变的通知,在转屏的时候,不仅是orientation发生了改变,screensize同样也发生了改变所以要添加“screenSize”)
这种情况下横竖屏切换后不再重建Activity。同时会调用如下方法:

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

通过代码验证:
Activity添加android:configChanges=”orientation|screenSize”

<activity
   android:name=".develop.ActivityA"
   android:configChanges="orientation|screenSize"
   android:label="@string/app_name"
   android:theme="@style/AppTheme.NoActionBar">
     <intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
</activity>
public class ActivityA extends Activity {

  @Override
  public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
     Log.i("axe.mg","onConfigurationChanged");
  }

   @Override
   protected void onSaveInstanceState(Bundle outState) {
     super.onSaveInstanceState(outState);
     outState.putString("key","value_string");
     Log.i("axe.mg","onSaveInstanceState");
   }

   @Override
   protected void onRestoreInstanceState(Bundle savedInstanceState) {
     super.onRestoreInstanceState(savedInstanceState);
     String str =   savedInstanceState.getString("key");
     Log.i("axe.mg","onRestoreInstanceState");Log.i("axe.mg","get value:"+str);
   }

   @Override
   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.test_layout);
     Log.i("axe.mg","onCreate()");
   }

   @Override
   protected void onRestart() {
     super.onRestart();
     Log.i("axe.mg","onRestart");
   }

   @Override
   protected void onStart() {
     super.onStart();
     Log.i("axe.mg","onStart()");
   }

   @Override
   protected void onResume() {
     super.onResume();
     Log.i("axe.mg","onResume()");
   }

   @Override
   protected void onPause() {
     super.onPause();
     Log.i("axe.mg","onPause()");
   }

   @Override
   protected void onStop() {
     super.onStop();
     Log.i("axe.mg","onStop()");
   }

   @Override
   protected void onDestroy() {
     super.onDestroy();
     Log.i("axe.mg","onDestroy()");
   }

横竖平切换后:

09-29 00:54:00.849 21338-21338/com.mg.axe.androiddevelop I/axe.mg: onConfigurationChanged

通过Log分析:
此时Activity不再重建, 不会调用生命周期的方法,也不会调用onSaveInstanceState和onRestoreInstanceState。会调用onConfigurationChanged方法。

+++++++++附件信息:configChanges属性的值+++++++++++

通过设置这个属性可以使Activity捕捉设备状态变化,以下是可以被识别的内容:
设置方法:将下列字段用“|”符号分隔开,例如:“locale|navigation|orientation

“mcc” 国际移动用户识别码所属国家代号是改变了—– sim被侦测到了,去更新mcc mcc是移动用户所属国家代号
“mnc” 国际移动用户识别码的移动网号码是改变了—— sim被侦测到了,去更新mnc MNC是移动网号码,最多由两位数字组成,用于识别移动用户所归属的移动通信网
“locale” 地址改变了—–用户选择了一个新的语言会显示出来
“touchscreen” 触摸屏是改变了——通常是不会发生的
“keyboard” 键盘发生了改变—-例如用户用了外部的键盘
“keyboardHidden” 键盘的可用性发生了改变
“navigation” 导航发生了变化—–通常也不会发生
“screenLayout” 屏幕的显示发生了变化——不同的显示被激活
“fontScale” 字体比例发生了变化—-选择了不同的全局字体
“uiMode” 用户的模式发生了变化
“orientation” 屏幕方向改变了
“screenSize” 屏幕大小改变了
“smallestScreenSize” 屏幕的物理大小改变了,如:连接到一个外部的屏幕上

参考链接:
http://www.cnblogs.com/-cyb/articles/Android_onConfigurationChanged.html (要添加screenSize的问题)
http://www.cnblogs.com/carlo/p/4311010.html (附件信息:configChanges属性的值)

参考书籍:Android开发艺术探索。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值