设备配置(Device Configuration)改变时的处理方法

当设备在横纵屏切换时,当前Activity的状态变化过程是:onPause()->onStop()->onDestroy()->onCreate()->onStart()->onResume()。

这样会导致什么样的问题呢?假如当前Activity所使用的一些局部变量在重新onCreate后就不是原来的值了,也就是当前Activity所依附的值被改变了,我们可以使用的解决方案是:重载onSaveInstanceState(Bundle)方法,在Activity销毁的时候可以将一些要保存数据存放到Bundle中,这样在重新onCreate时,超类中的onCreate函数会将保存数据的Bundle传到当前Activity中,我们可以使用该Bundle来恢复状态。但是其局限性就很明显了,因为Bundle保存的是一些key-value对。

如果我们想要横纵屏在切换时不重新销毁再创建Activity呢?我先总结一些关于设备配置(Device Configuration)的知识。

设备的配置包括屏幕的密度,尺寸,方向和键盘的类型,语言等。我们常用的有locale(语言),keyboard(弹出软键盘),keyboardHidden(隐藏软键盘),orientation(方向)。这些设备配置发生改变时,系统默认的处理方式是销毁再重新创建Activity。但是我们可以通过设置指定当某些配置信息发生改变时不销毁并重建Activity。方法是这样的。在AndroidManifest.xml文件中的相应的Activity标签下设置android.configChanges的值,我们一般将其设为keyboardHidden|orientation|locale意思是当设备的这些配置发生变化时,会调用Activity的onConfigChanged(Configuration)函数,而不会去销毁并重建Activity了。如果我们想要捕获到配置的变化并进行操作,可以重载onConfigChanged函数,需AndroidManifest.xml中添加权限设置,<user-permission android:name="android.permission.CHANGE_CONFIGURATION"/>.

其实对于横纵屏切换导致重建Activity的问题有一个很简单的解决方法,就是直接设置Activity.screenOrientation="portrait"或“land”。这样就不会横纵切换了。

但是在Android 3.2之后,需要在android.configChanges中添加screenSize,否则在横纵屏切换时,仍然会销毁重建Activity。原因是:Google在Android3.2版本中添加了screenSize,我们在横纵屏切换时,不仅orientation发生了变化,而且sreenSize也发生了变化。源代码中时这样做的:

int diff = activity.mCurrentConfig.diff(config);

if (diff != 0) {                

// If this activity doesn't handle any of the config changes then don't bother calling onConfigurationChanged as we'regoing to destroy it.

if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) {

shouldChangeConfig = true;

}

}

 

public int getRealConfigChanged() {

return applicationInfo.targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB_MR2 ? (configChanges | ActivityInfo.CONFIG_SCREEN_SIZE

| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) : configChanges;

}
最后把demo代码贴上来。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testonconfigurationchanged"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="14" />
    <uses-permission 
        android:name="android.permission.CHANGE_CONFIGURATION"/>
        
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:configChanges="orientation|keyboardHidden|screenSize" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

public class MainActivity extends Activity {

	final static String TAG="MainActivity";
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		Log.i(TAG,"onCreate");
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}
	
	
	@Override
	public void onConfigurationChanged(Configuration news){
		if(news.orientation==ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE){
			Log.i(TAG, "横屏");
		}else if(news.orientation==ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
			Log.i(TAG, "纵屏");
		}
		super.onConfigurationChanged(news);
	}
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值