第十一課:啓動、關閉 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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章