Activity生命周期与状态保存

来源:互联网 发布:中国大数据产业观察网 编辑:程序博客网 时间:2024/06/04 23:25

为了搞清楚Acitivity的生命周期,进一步了解我们需要在什么时候保存需要的信息,我们需要几个视图

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/my_activity"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <TextView        android:id="@+id/tv_number1"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <EditText        android:id="@+id/editText1"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:hint="这是Activity中有id的EditText"        android:ems="10" >        <requestFocus />    </EditText>    <EditText        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:hint="这是Activity中没有id的EditText"        android:ems="10" />    <LinearLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center" >        <Button            android:id="@+id/bt_show_text"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="显示" />        <Button            android:id="@+id/bt_switch_orientation"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="改变屏幕方向" />    </LinearLayout></LinearLayout>
如图


注:由于我的AVD模拟器怎么都无法横屏(使用CTRL+F11、CTRL+F12、小键盘7和9都试了,只是把屏幕整体横过来,而没有重新布局),所以我使用一个Button来手动切换横竖屏

在Activity中声明私有变量

private String mText = "显示输入信息";private TextView mShowText;private EditText mInput;private Button mShowTextButton;private Button mSwitchOrientationButton;//改变屏幕方向的按钮

暂时不管改变屏幕方向的按钮,在onCreate()方法中初始化其他变量并设置监听

mShowText = (TextView) findViewById(R.id.tv_number1);mInput = (EditText) findViewById(R.id.editText1);//如果mShowText为空,则显示字符串mText的值if(TextUtils.isEmpty(mShowText.getText().toString())) {mShowText.setText(mText);}mFragment = new ScreenOrientationFragment();mShowTextButton = (Button) findViewById(R.id.bt_show_text);mShowTextButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {mText = mInput.getText().toString();mShowText.setText(mText);}});

覆盖生命周期方法,先在onCreate()中添加以下代码

Log.d(TAG, "onCreate(Bundle)");
在Activity中添加常量

private static final String TAG = "LifecycleActivity"; 
 

覆盖其他生命周期方法
@Overrideprotected void onStart(){super.onStart();Log.d(TAG, "onStart()");}@Overrideprotected void onRestart(){super.onRestart();Log.d(TAG, "onRestart()");}@Overrideprotected void onResume(){super.onResume();Log.d(TAG, "onResume()");}@Overrideprotected void onPause(){super.onPause();Log.d(TAG, "onPause()");}@Overrideprotected void onStop(){super.onStop();Log.d(TAG, "onStop()");}@Overrideprotected void onDestroy(){super.onDestroy();Log.d(TAG, "onDestroy()");}@Overrideprotected void onSaveInstanceState(Bundle savedInstanceState){super.onSaveInstanceState(savedInstanceState);Log.d(TAG, "onSaveInstanceState(Bundle)");}@Overrideprotected void onRestoreInstanceState(Bundle savedInstanceState){super.onRestoreInstanceState(savedInstanceState);Log.d(TAG, "onRestoreInstanceState(Bundle)");}
运行程序,当第一次加载活动时,LogCat窗口中可以看到类似以下日志:
07-07 06:27:11.850: D/LifecycleActivity(2360): onCreate(Bundle)
07-07 06:27:12.600: D/LifecycleActivity(2360): onStart()
07-07 06:27:12.600: D/LifecycleActivity(2360): onResume()

进行准备工作:在两个EditText中输入任意内容,再点击“显示”按钮,使TextView中的内容更新为第一个EditText中的值


点击模拟器上的主屏幕按钮,活动进入后台,LogCat

07-07 11:12:23.550: D/LifecycleActivity(2360): onPause()
07-07 11:12:29.710: D/LifecycleActivity(2360): onSaveInstanceState(Bundle)
07-07 11:12:29.710: D/LifecycleActivity(2360): onStop()

再点击应用图标回到应用,LogCat

07-07 11:15:01.330: D/LifecycleActivity(2360): onRestart()
07-07 11:15:01.330: D/LifecycleActivity(2360): onStart()
07-07 11:15:01.350: D/LifecycleActivity(2360): onResume()

可以看到之前输入的信息和TextView中的信息原封不动地还原了。

再来看另外一种情况(模拟系统回收内存销毁activity),先在模拟器中打开Settings,找到Development options选项,勾选Don't keep activities选项


再回到之前的应用活动,重复准备工作的操作,当点击主屏幕按钮后,再来看LogCat

07-07 11:27:44.200: D/LifecycleActivity(2360): onPause()
07-07 11:27:51.730: D/LifecycleActivity(2360): onSaveInstanceState(Bundle)
07-07 11:27:51.730: D/LifecycleActivity(2360): onStop()
07-07 11:27:51.810: D/LifecycleActivity(2360): onDestroy()

注意最后一行,调用了onDestroy()来销毁活动,重新运行应用

07-07 11:30:20.920: D/LifecycleActivity(2360): onCreate(Bundle)
07-07 11:30:22.310: D/LifecycleActivity(2360): onStart()
07-07 11:30:22.410: D/LifecycleActivity(2360): onRestoreInstanceState(Bundle)
07-07 11:30:22.420: D/LifecycleActivity(2360): onResume()


只有设置了id的EditText中的信息被还原了,没有id的EditText中的信息就丢失了。而对于TextView,无论是否有id,系统都不会保存其中的内容(为什么?以后再慢慢研究)。

当屏幕旋转时会发生什么呢?先给“改变屏幕方向”按钮初始化并设置监听

mSwitchOrientationButton = (Button) findViewById(R.id.bt_switch_orientation);mSwitchOrientationButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);} else {setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);}}});
回到应用,重复准备工作操作,点击“改变屏幕方向”按钮(该按钮只是改变了活动的显示方向,还需要按CTRL+F11使模拟器屏幕方向改变),查看LogCat

07-07 11:51:31.120: D/LifecycleActivity(2360): onPause()
07-07 11:51:31.130: D/LifecycleActivity(2360): onSaveInstanceState(Bundle)
07-07 11:51:31.130: D/LifecycleActivity(2360): onStop()
07-07 11:51:31.130: D/LifecycleActivity(2360): onDestroy()
07-07 11:51:31.680: D/LifecycleActivity(2360): onCreate(Bundle)
07-07 11:51:32.310: D/LifecycleActivity(2360): onStart()
07-07 11:51:32.310: D/LifecycleActivity(2360): onRestoreInstanceState(Bundle)
07-07 11:51:32.310: D/LifecycleActivity(2360): onResume()

可以看到系统是将活动销毁后再新建一个活动


跟之前的结果一样。

从上面的测试中发现,活动的onSaveInstanceState(Bundle)被调用了,所以在大多数情况下,我们可以在onSaveInstanceState(Bundle)方法中保存我们需要的数据。

但是和单击主屏幕不一样的是,单击后退按钮时,无论是否勾选Don't keep activities,系统总是会销毁当前activity,看LogCat

07-07 13:12:34.990: D/LifecycleActivity(2360): onPause()
07-07 13:12:39.940: D/LifecycleActivity(2360): onStop()
07-07 13:12:39.940: D/LifecycleActivity(2360): onDestroy()

这时直接onDestroy了,而没有调用onSaveInstanceState。所以在点击后退按钮的情况下,再想通过onSaveInstanceState(Bundle)来保存并恢复数据就不太现实了。不过可以在onPause()中,借助数据库或者文件来保存需要的数据。

复制去Google翻译翻译结果
的onSaveInstanceState
0 0
原创粉丝点击