Activity生命周期与状态保存

为了搞清楚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() {

			@Override
			public void onClick(View v) {
				mText = mInput.getText().toString();
				mShowText.setText(mText);
			}
		});

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

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

private static final String TAG = "LifecycleActivity"; 
 

覆盖其他生命周期方法
	@Override
	protected void onStart(){
		super.onStart();
		Log.d(TAG, "onStart()");
	}
	
	@Override
	protected void onRestart(){
		super.onRestart();
		Log.d(TAG, "onRestart()");
	}
	
	@Override
	protected void onResume(){
		super.onResume();
		Log.d(TAG, "onResume()");
	}
	
	@Override
	protected void onPause(){
		super.onPause();
		Log.d(TAG, "onPause()");
	}
	
	@Override
	protected void onStop(){
		super.onStop();
		Log.d(TAG, "onStop()");
	}
	
	@Override
	protected void onDestroy(){
		super.onDestroy();
		Log.d(TAG, "onDestroy()");
	}
	
	@Override
	protected void onSaveInstanceState(Bundle savedInstanceState){
		super.onSaveInstanceState(savedInstanceState);
		Log.d(TAG, "onSaveInstanceState(Bundle)");
	}
	
	@Override
	protected 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() {

			@Override
			public 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值