onConfigurationChanged详解及onConfigurationChanged未被调用的问题
android:onConfigurationChanged实际上对应的是Activity里的onConfigurationChanged()方法,在项目的配置清单文件中添加上述代码的含义是表示在改变屏幕方向、弹出软件盘和隐藏软键盘时,不再去执行onCreate()方法,而是直接执行onConfigurationChanged()。如果不申明此段代码,按照Activity的生命周期,都会去执行一次onCreate()方法,而onCreate()方法通常会在显示之前做一些初始化工作。所以如果改变屏幕方向这样的操作都去执行onCreate()方法,就有可能造成重复的初始化,降低程序效率是必然的了,而且更有可能因为重复的初始化而导致数据的丢失。这是需要千万避免的。
通过Demo可以证明一个问题:
public class ConsoleActivity extends Activity { private String str = "0"; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //模拟数据初始化 str = "1"; Log.e("FHT", "onCreate:" + str); } @Override protected void onStart() { super.onStart(); //模拟显示之后,数据发生改变 str = (new Date()).getTime() + ""; Log.e("FHT", "onStart:" + str); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); Log.e("FHT", "onConfigurationChanged:" + str); } }
![](http://www.jcodecraeer.com/uploads/allimg/121106/003KHR8-0.jpg)
从上图可以看出,当屏幕方向发生了三次翻转,三次翻转都没有重新进入onCreate()方法,所以str的值得以延续,如果去除AndroidManifest.xml中关于onConfigurationChanged的相关代码,程序的执行顺序将发生变化,每次屏幕方向的变化都将引起str值的重置。这是大多数开发过程中所不希望看到的。
另外需要注意的是onConfigurationChanged()方法中的:super.onConfigurationChanged(newConfig);一定不能省去,否则将引发:android.app.SuperNotCalledException 异常。如果改变了系统屏幕的设置方向,我们不妨可以这么认为,它算是一个触发事件的开始吧,那么假使有人触发了这个事件,我们是否能够直接进行某些操作呢,如改变界面的UI等?当然不行,因为上面的范例,我们直接是借助setRequestedOrientation这个方法设置的,而在这个方法中无法实现其他的操作。
android中,我们借助的是另外一个事件——onConfigerationChanged,这个方法也是能够重写的。示范代码功能很简单,就是在改变屏幕的方向的同时,也改变了点击按钮的text:
import android.app.Activity; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class onConfigurationChangedTest extends Activity implements OnClickListener{ private Button mButton; int intCurrentOrientation; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.Init(); mButton.setOnClickListener(this); } public void Init() { mButton=(Button) this.findViewById(R.id.Button01); intCurrentOrientation=this.getRequestedOrientation(); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch(v.getId()) { case R.id.Button01: if(this.intCurrentOrientation==ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else if(this.intCurrentOrientation==ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } break; } } @Override public void setRequestedOrientation(int requestedOrientation) { // TODO Auto-generated method stub super.setRequestedOrientation(requestedOrientation); } @Override public int getRequestedOrientation() { // TODO Auto-generated method stub return super.getRequestedOrientation(); } @Override public void onConfigurationChanged(Configuration newConfig) { // TODO Auto-generated method stub if(newConfig.orientation==Configuration.ORIENTATION_PORTRAIT) { mButton.setText("现在是竖屏"); System.out.println("435435435456454"); } if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE) { mButton.setText("现在是横屏"); System.out.println("kjkjhugggtvg"); } super.onConfigurationChanged(newConfig); } }
这里需要注意几点,就是首先要设置初始的Orientation,而且还要设置捕捉更改的权限—— Android.permission.CHANGE_CONFIGURATION,还有一点,就是必须在Activity里设置 configChanges属性。这里我们不妨理解为声明!!为了好理解,我也把AndroidManifest.xml文件贴在这里了
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mobile.allove.wfp" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".onConfigurationChangedTest" android:label="@string/app_name" android:screenOrientation="portrait" android:configChanges="orientation"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="3" /> <uses-permission android:name="android.permission.CHANGE_CONFIGURATION"></uses-permission> </manifest>
解决onConfigurationChanged不被调用的问题:
如果你的TargetSdk超过12,然后你想在安装了Android API level 超过12的设备上使用onConfigurationChanged,你就必须再对应的Activity里加上对应的screenSize。 一句话答案,把android:configChanges="orientation" 改成android:configChanges="orientation|screenSize" 就OK了。