第十一课:启动、关闭 Activity 及其之间的数据交换

Activity 的启动和关闭

一个 Android 应用通常都会包含多个 Activity,但后只有一个 Activity 会作为程序的入口。其他的 Activity 都需要依赖入口 Activity 或者入口启动的其他 Activity 来启动。

Activity 启动其他 Activity 有如下两种方法:

startActivity(Intent intent):启动其它 Activity。

startActivityForResult(Intent intent, int requestCode):以指定请求码(requestCode)启动 Activity,而且程序将会得到新启动 Activity 的结果(重写onActivityResult(...)方法获取)。

上面两个方法都用到了 Intent 参数,Intent 是 Android 应用里各组件之间通信的重要方式,一个 Activity 通过 Intent 来表达自己的“意图”。(想要启动哪个组件,被启动的组件既可以是 Activity 组件,也可以是 Service 组件。

相对的,也有两个关闭Activity的方法对应这两个启动的方法:

finish():结束当前 Activity。

finishActivity(int requestCode):结束以 startActivityForResult(Intent intent, int requestCode) 方法启动的 Activity。


例1:在 Activity 中启动其他 Activity

StartActivity.java

<span style="font-family:Microsoft YaHei;">public class StartActivity extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		// 获取应用程序中的bn按钮
		Button bn = (Button) findViewById(R.id.bn);
		// 为bn按钮绑定事件监听器
		bn.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View source)
			{
				// 创建需要启动的Activity对应的Intent
				Intent intent = new Intent(StartActivity.this,
						SecondActivity.class);
				// 启动intent对应的Activity
				startActivity(intent);
			}
		});
	}
}</span>

SecondActivity.java

<span style="font-family:Microsoft YaHei;">public class SecondActivity extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.second);
		// 获取应用程序中的previous按钮
		Button previous = (Button) findViewById(R.id.previous);
		// 获取应用程序中的close按钮
		Button close = (Button) findViewById(R.id.close);
		// 为previous按钮绑定事件监听器
		previous.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View source)
			{
				// 获取启动当前Activity的上一个Intent
				Intent intent = new Intent(SecondActivity.this,
						StartActivity.class);
				// 启动intent对应的Activity
				startActivity(intent);
			}
		});
		// 为close按钮绑定事件监听器
		close.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View source)
			{
				// 获取启动当前Activity的上一个Intent
				Intent intent = new Intent(SecondActivity.this,
						StartActivity.class);
				// 启动intent对应的Activity
				startActivity(intent);
				// 结束当前Activity
				finish();
			}
		});
	}
}</span>


例2:

startActivity()只有一个参数,如果需要向新打开的Activity传递参数,我们得换一个函数了, Android提供了startSubActivity(Intent,int)这个函数来实现这个功能。

函数原型为: public void startSubActivity(Intent intent, int requestCode)这里的requestCode用来标识某一个调用,一般由我们定义一个常量。

如何把参数传过去呢? Intent 类在提供 setClass() 函数的同时也提供了一个 setData() 函数。

        函数原型为:public Intent setData(ContentURI data)。参数类型是 ContentURI,它的详细内容下回再分析,现在就把它当成一个 String 类型来用吧。参数带到新的 Activity 后,同样用 Activity.getIntent() 函数可以得到当前过来的 Intent 对象,然后用 getData() 就取到参数了。

把参数带回来的方法是 Activity.setResult(),它有几个形式,现在先看最简单的一个吧。

函数原型是:public final void setResult(int resultCode, String data)。resultCode 是返回代码,同样用来标识一个返回类型,而 data 则是它要返回的参数。在原来的 Activity 中的事件处理回调函数 onActivityResult,会被系统调用,从它的参数里可以得到返回值。

函数原型为:protected void onActivityResult(int requestCode, int resultCode,String data, Bundle extras)

这里的 requestCode 就是前面启动新 Activity 时的带过去的 requestCode,而 resultCode 则关联上了 setResult 中的 resultCode ,data 是参数,extras 也是一个很重要的东西,后面再研究一下它的作用。

如:
A-Activity 需要在 B-Activtiy 中执行一些数据操作,而 B-Activity 又要将执行操作数据的结果返回给 A-Activtiy


//看效果


<span style="font-family:Microsoft YaHei;">public class ActivityResultDemoActivity extends Activity
{
	private Button button_start_task;
	private TextView TextView_result;
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		button_start_task=(Button) findViewById(R.id.button_start_task);
		TextView_result=(TextView) findViewById(R.id.TextView_result);
		button_start_task.setOnClickListener(new button_start_task_Listener());
	}
	private class button_start_task_Listener implements OnClickListener
	{
		public void onClick(View v)
		{
			Intent intent=new Intent(ActivityResultDemoActivity.this,SimpleTaskActivity.class);
			//关键点来了,使用startActivityForResult来启动
			startActivityForResult(intent, 100);
		}
	}
	/**
	 * 复写onActivityResult,这个方法
	 * 是要等到SimpleTaskActivity点了提交过后才会执行的
	 */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		//可以根据多个请求代码来作相应的操作
		if(20==resultCode)
		{
			String bookname=data.getExtras().getString("bookname");
			String booksale=data.getExtras().getString("booksale");
			TextView_result.setText("书籍名称:"+bookname+"书籍价钱"+booksale+"元");
		}
		super.onActivityResult(requestCode, resultCode, data);
	}
}</span>

<span style="font-family:Microsoft YaHei;">public class SimpleTaskActivity extends Activity
{
	private EditText EditText_bookname;
	private EditText EditText_booksale;
	private Button Button_task_fulfill;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main2);
		
		EditText_bookname=(EditText) findViewById(R.id.EditText_bookname);
		EditText_booksale=(EditText) findViewById(R.id.EditText_booksale);
		Button_task_fulfill=(Button) findViewById(R.id.Button_task_fulfill);
		Button_task_fulfill.setOnClickListener(new Button_task_fulfill_Listener());
	}
	private class Button_task_fulfill_Listener implements OnClickListener
	{
		public void onClick(View v)
		{
			String str_bookname=EditText_bookname.getText().toString();
			String str_booksale=EditText_booksale.getText().toString();
			
			//判断空,我就不判断了。。。。
			Intent data=new Intent();
			data.putExtra("bookname", str_bookname);
			data.putExtra("booksale", str_booksale);
			//请求代码可以自己设置,这里设置成20
			setResult(20, data);
			//关闭掉这个Activity
			finish();
		}
	}
}
</span>

使用 Bundle 在 Activity 之间交换数据

当一个 Activity 启动另一个 Activity 时,常常要传递一些数据过去,就像 Web 应用从一个 Servlet 跳到另一个 Servelet 时,习惯把数据放入到 requestScope、sessionScope 中。而对于 Activity,在 Activity 之间进行数据交换更为简单,因为两个 Activity 之间本来就有一个“信使”:Intent,因此我们吧数据放到 Intent 中即可。
Intent提供了多个重载方法来“携带”额外的数据:
putExtras(Bundle data):向 Intent 中放入需要“携带”的数据包。(一个携带数据的Bundle对象)。
Bundle getExtras():取出 Intent 所“携带”的数据包。(一个携带数据的Bundle对象)。
putExtras(String name, Xxx value):向 Intent 中按 key-value 对的形式存入数据。
Bundle getExtras(String name):从 Intent 中按 key 取出指定类型的数据。

Bundle 数据包的操作方式:
putXxx(String key, Xxx data):向 Bundle 中放入 Int,Long 等各种类型的数据。
putSerializable(String key, Serializable data):向 Bundle 中放入一个可以序列化的对象,此对象实现 java.util.io 中的 Serializable 接口即可。
取出数据时的方法:
getXxx(String key):从 Bundle 中取出 Int,Long 等各种类型的数据。
getSerializable(String key, Serializable data):从 Bundle 中取出一个可以序列化的对象。

Intent 提供的 putExtras(String name, Xxx value)、Bundle getExtras(String name) 方法,只是一个便捷的方法,这些方法是直接存、取 Intent 中所携带的 Bundle 中的数据。
Intent 中的 putExtras(String name, Xxx value) 方法是“智能”的,当程序调用 Intent 的 putExtras(String name, Xxx value) 方法向 Intent 中存入数据时,如果该 Intent 中已经携带了 Bundle 对象,则该方法直接向 Intent 所携带的 Bundle 存入数据;如果 Intent 还没有携带 Bundle 对象, putExtras(String name, Xxx value) 方法会先为 Intent 创建一个 Bundle,再向 Bundle 存入数据。

例1:两个 Activity 通过 Intent 交换数据
main.xml
<span style="font-family:Microsoft YaHei;"><?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	>
<TextView  
	android:layout_width="fill_parent" 
	android:layout_height="wrap_content" 
	android:text="请输入您的注册信息"
	android:textSize="20sp"
	/>	
<TableRow>
<TextView  
	android:layout_width="fill_parent" 
	android:layout_height="wrap_content" 
	android:text="用户名 :"
	android:textSize="16sp"	
	/>
<!-- 定义一个EditText,用于收集用户的帐号 -->
<EditText
	android:id="@+id/name"
	android:layout_width="fill_parent" 
	android:layout_height="wrap_content" 
	android:hint="请填写想注册的帐号"
	android:selectAllOnFocus="true"		
	/>
</TableRow>
<TableRow>
<TextView  
	android:layout_width="fill_parent" 
	android:layout_height="wrap_content" 
	android:text="密码 :"
	android:textSize="16sp"		
	/>
<!-- 用于收集用户的密码 -->
<EditText
	android:id="@+id/passwd"
	android:layout_width="fill_parent" 
	android:layout_height="wrap_content" 
	android:password="true"
	android:selectAllOnFocus="true"		
	/>
</TableRow>
<TableRow>
<TextView  
	android:layout_width="fill_parent" 
	android:layout_height="wrap_content" 
	android:text="性别 :"
	android:textSize="16sp"		
	/>
<!-- 定义一组单选框,用于收集用户注册的性别 -->
<RadioGroup
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:orientation="horizontal"
>
<RadioButton
	android:id="@+id/male" 
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:text="男"
	android:textSize="16sp"		
/>
<RadioButton
	android:id="@+id/female" 
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"			
	android:text="女"
	android:textSize="16sp"	
/>
</RadioGroup>
</TableRow>	
<Button
	android:id="@+id/bn" 
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"			
	android:text="注册"
	android:textSize="16sp"	
/>
</TableLayout></span>

BundleTest.java
<span style="font-family:Microsoft YaHei;">public class BundleTest extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		Button bn = (Button) findViewById(R.id.bn);
		bn.setOnClickListener(new OnClickListener()
		{
			public void onClick(View v)
			{
				EditText name = (EditText)findViewById(R.id.name);
				EditText passwd = (EditText)findViewById(R.id.passwd);
				RadioButton male = (RadioButton) findViewById(R.id.male);
				String gender = male.isChecked() ? "男 " : "女";
				Person p = new Person(name.getText().toString(), passwd
						.getText().toString(), gender);
				// 创建一个Bundle对象
				Bundle data = new Bundle();
				data.putSerializable("person", p);
				// 创建一个Intent
				Intent intent = new Intent(BundleTest.this,
						ResultActivity.class);
				intent.putExtras(data);
				// 启动intent对应的Activity
				startActivity(intent);
			}
		});
	}
}</span>

result.xml
<span style="font-family:Microsoft YaHei;"><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:orientation="vertical"
	>
<!-- 定义三个TextView,用于显示用户输入的数据 -->
<TextView 
	android:id="@+id/name"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:textSize="18sp"
	/>
<TextView 
	android:id="@+id/passwd"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:textSize="18sp"
	/>
<TextView 
	android:id="@+id/gender"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:textSize="18sp"
	/>	
</LinearLayout></span>

ResultBundle.java
<span style="font-family:Microsoft YaHei;">public class ResultActivity extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.result);
		TextView name = (TextView) findViewById(R.id.name);
		TextView passwd = (TextView) findViewById(R.id.passwd);
		TextView gender = (TextView) findViewById(R.id.gender);
		// 获取启动该Result的Intent
		Intent intent = getIntent();
		// 直接通过Intent取出它所携带的Bundle数据包中的数据
		Person p = (Person) intent.getSerializableExtra("person");
		name.setText("您的用户名为:" + p.getName());
		passwd.setText("您的密码为:" + p.getPass());
		gender.setText("您的性别为:" + p.getGender());
	}
}</span>


发布了34 篇原创文章 · 获赞 32 · 访问量 11万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章