前一讲我们通过一个发送短信的小例子讲解了Activity在横竖屏切换时的生命周期情况。其实那个程序还有一个Bug,当我们编辑了短信将要发送的时候,如果你不小心把手机屏幕切换了一下,然后你会发现你编辑的短信已经被清空了,这时你又要重新编辑。试想一下,当我们好不容易编辑了一条短信,然后突然一个电话打过来了,然后你接完电话返回到短信的界面时,你却发现你刚才编辑的短信成了空白,你心底一定会骂,是哪个二货设计的这个功能,太他妈不人性化了。 那么这节我们就来解决这个问题。

当然,保存Activity状态的方法有多种,我们这讲来介绍一下通过重写Activity的onSaveInstanceState事件处理函数来保存Activity的状态。

我们修改一下上节中发短信的小例子,在SmsActivity.java中添加如下代码:

package com.liuzhichao.sms;

import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class SmsActivity extends Activity {
	private static final String TAG="SmsActivity";
	//声明组件
    private EditText et_phone;
    private EditText et_content;
    private Button btn_Send;
    private Button btn_Cancel;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Log.i(TAG, "----onCreate()----");
        //根据ID获取组件
        et_phone = (EditText)findViewById(R.id.et_phone);
        et_content = (EditText)findViewById(R.id.et_content);
        btn_Send = (Button)findViewById(R.id.btn_Send);
        btn_Cancel = (Button)findViewById(R.id.btn_Cancel);

        //注册按钮单击事件
        btn_Send.setOnClickListener(btn_Send_ClickListener);
        btn_Cancel.setOnClickListener(btn_Cancel_ClickListener);

        //应用程序被迫重启,那么,保存的Bundle会传入到onRestoreInstanceState和onCreate方法中
        //如果savedInstanceState不为空
        if (null != savedInstanceState ){
        	//判断savedInstanceState中是否保存了用户输入的手机号码
        	if (savedInstanceState.containsKey("phoneString")) {
        		et_phone.setText(savedInstanceState.getString("phoneString"));
			}
        	//判断savedInstanceState中是否保存了用户输入的短信内容
        	if (savedInstanceState.containsKey("contentString")) {
				et_content.setText(savedInstanceState.getString("contentString"));
			}
        }
    }

    /**
     * 覆盖onSaveInstanceState保存用户输入的手机号码和短信内容
     * 使用它的Bundle参数来保存实例的值
     */
    @Override
	protected void onSaveInstanceState(Bundle outState) {

		String phoneString = et_phone.getText().toString();
		String contentString=et_content.getText().toString();

		//如果手机号码和短信内容不为空
		if (!"".endsWith(phoneString)) {
			outState.putString("phoneString", phoneString);
		}
		if (!"".endsWith(contentString)) {
			outState.putString("contentString", contentString);
		}

		super.onSaveInstanceState(outState);
	}

	//发送按钮事件处理
    private OnClickListener btn_Send_ClickListener = new OnClickListener() {
		public void onClick(View v) {
			//获取电话号码和知道内容
			String phoneString = et_phone.getText().toString();
			String contentString=et_content.getText().toString();

			//判断号码是否为空
			if("".equals(phoneString)){
				//提示电话号码不能为空
				Toast.makeText(SmsActivity.this, R.string.tip_phone, Toast.LENGTH_LONG).show();
				et_phone.requestFocus(); //让号码框获取焦点
				return;
			}
			//判断短信内容是否为空
			if ("".equals(contentString)) {
				//提示短信内容不为能空
				Toast.makeText(SmsActivity.this, R.string.tip_content, Toast.LENGTH_LONG).show();
				et_content.requestFocus();//让短信内容输入框获取焦点
				return;
			}

			 SmsManager sms = SmsManager.getDefault();
			 // 如果短信没有超过限制长度,则返回一个长度的List。
			  List <String>  texts = sms.divideMessage(contentString);
			  for (String text:texts) {
				  sms.sendTextMessage(phoneString, null, text, null, null);
				  //发送成功后清空号码和短信内容
				  et_content.setText(&quot;&quot;);
				  et_phone.setText(&quot;&quot;);
				  Log.i(TAG, &quot;短信发送成功!&quot;);
			}
		}
	};

	//取消按钮事件处理
	 private OnClickListener btn_Cancel_ClickListener = new OnClickListener() {
			public void onClick(View v) {
				SmsActivity.this.finish();
			}
		};

}

onSaveInstanceState()这个处理函数会在Activity的Active生命周期结束时触发,但仅在它不是显式地结束(即异常结束)。因此,它一般用于确保在单个用户会话中的Active生命周期间Activity状态的一致性。

注:有一点很重要的是,记住onSaveInstanceState仅在Activity变成非Active状态时调用,但不在调用finish来关闭它或用户按下Back按钮时调用。由于onSaveInstanceState()并不是每次销毁时都会调用,所以不要在其中保存那些需要永久化的数据,执行保存那些数据的最好地方是:onPause()中。