根據文檔的解釋,Activity是Android開發中非常重要的一個基礎類。我把它想像成J2ME中的Display類,或者是Win32平台上的Form類,也許不準確,但是它的重要性我覺得應該是一樣的(當然,如果我們寫的是一個沒有介面的應用,例如後台啟動並執行服務之類的,可以不用Display的)。
1. 在一個Activity中使用多個View
如果把Activity看作MVC中的Control?它負責管理UI和接受事件(包括使用者的輸入),雖然說一個Activity通常對應一個螢幕,但事實上,我們是可以只用一個Activity管理多個不同的View來實現簡單的邏輯。
首先,我們增加一個新的資源描述layout/second.xml。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView id="@+id/txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello 中國"
/>
<Button id="@+id/go2"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="back">
<requestFocus />
</Button>
</LinearLayout>
除了一個“Hello中國”以外,增加一個按鈕可以返回前一個介面。然後,在代碼中我們要為helloTwo增加兩個方法,setViewOneCommand和setViewTwoCommand,分別處理一下在不同介面時,從資源裡載入組件並為組件綁定一個事件處理器。
public void setViewOneCommand()
...{
Button btn = (Button)findViewById(R.id.go);
btn.setOnClickListener(new View.OnClickListener()
...{
public void onClick(View v)
...{
helloTwo.this.setContentView(R.layout.second);
helloTwo.this.setViewTwoCommand();
}
});
Button btnExit=(Button)findViewById(R.id.exit);
btnExit.setOnClickListener(new View.OnClickListener()...{
public void onClick(View v)...{
helloTwo.this.finish();
}
});
}
public void setViewTwoCommand()
...{
Button btnBack=(Button)findViewById(R.id.go2);
btnBack.setOnClickListener(new View.OnClickListener()...{
public void onClick(View v)...{
helloTwo.this.setContentView(R.layout.main);
helloTwo.this.setViewOneCommand();
}
});
}
最後,我們需要在onCreate的時候,也就是啟動後的main介面上設定一下按鈕事件處理器。新的onCreate方法如下:
public void onCreate(Bundle icicle) ...{
super.onCreate(icicle);
setTheme(android.R.style.Theme_Dark);
setContentView(R.layout.main);
setViewOneCommand();
}
編譯,運行,OK。
2. 還是回到正道上,多個Activity之間的跳轉
Android中提供一個叫Intent的類來實現螢幕之間的跳轉,按文檔的說法,似乎他們也建議採用這種方法,Intent的用法比較複雜,現在我先看看它最簡單的用法。
先在應用中增加兩個Activity,這需要修改AndroidManifest.xml檔案了,如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.sharetop.android.hello.three">
<application android:icon="@drawable/icon">
<activity class=".HelloThree" android:label="@string/app_name">
<intent-filter>
<action android:value="android.intent.action.MAIN" />
<category android:value="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity class=".HelloThreeB" android:label="@string/app_name">
</activity>
</application>
</manifest>
很簡單,就是加一個標籤而已,新標籤的class是.HelloThreeB,顯示的應用標題與前一個Activity一樣而已,然後第二步就是修改一個HelloThree類的實現,在onCreate方法中綁定按鈕的事件處理器:
public void onCreate(Bundle icicle) ...{
super.onCreate(icicle);
setTheme(android.R.style.Theme_Dark);
setContentView(R.layout.main);
setViewOneCommand();
}
public void setViewOneCommand()
...{
Button btn = (Button)findViewById(R.id.go);
btn.setOnClickListener(new View.OnClickListener()
...{
public void onClick(View v)
...{
Intent intent = new Intent();
intent.setClass(HelloThree.this, HelloThreeB.class);
startActivity(intent);
finish();
}
});
Button btnExit=(Button)findViewById(R.id.exit);
btnExit.setOnClickListener(new View.OnClickListener()...{
public void onClick(View v)...{
HelloThree.this.finish();
}
});
}
這裡的跳轉功能用Intent來操作,它的最簡單用法就是用函數setClass()設定跳轉前後兩個Activity類的執行個體,然後調用Activity自己的startActivity(intent)即可。最後一句finish()表示將當前Activity關掉(如果不關掉會如何?你可以自己試一下看效果,事實上有時我們是不需要關掉當前Activity的)。
然後,我們同樣弄一個Activity類HelloThreeB,代碼與前面的差不多,只是將setClass的兩個參數反一下,這樣就可以簡單地實現在兩個Activity介面中來回切換的功能了。
3. 如果我想在兩個Activity之間進行資料交換,怎麼辦?
前例中的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也是一個很重要的東西,後面再研究一下它的作用。
下面,我們來看一下代碼吧,先看看HelloThree中的代碼:
public void setViewOneCommand()
...{
Button btn = (Button)findViewById(R.id.go);
btn.setOnClickListener(new View.OnClickListener()
...{
public void onClick(View v)
...{
try
...{
Intent intent = new Intent();
intent.setClass(HelloThree.this, HelloThreeB.class);
intent.setData(new ContentURI("One"));
startSubActivity(intent,REQUEST_TYPE_A);
}
catch(Exception ex)...{}
}
});
Button btnExit=(Button)findViewById(R.id.exit);
btnExit.setOnClickListener(new View.OnClickListener()...{
public void onClick(View v)...{
HelloThree.this.finish();
}
});
}
protected void onActivityResult(int requestCode, int resultCode,
String data, Bundle extras)
...{
if (requestCode == REQUEST_TYPE_A) ...{
if (resultCode == RESULT_OK) ...{
Log.v(TAG,data);
TextView txt = (TextView)findViewById(R.id.txt);
txt.setText(data);
}
}
}
這裡的REQUEST_TYPE_A是我們定義的一個常量。在onActivityResult中用它與RESULT_OK一起作為條件判斷如何處理傳回值,這裡只是簡單將TextView顯示值換成傳來的字串。
再來看看另一個HelloThreeB類的實現代碼:
private Intent i;
protected void onCreate(Bundle icicle) ...{
super.onCreate(icicle);
setContentView(R.layout.second);
i = getIntent();
android.util.Log.v(TAG,"onCreate");
Button btn = (Button)findViewById(R.id.go);
btn.setOnClickListener(new View.OnClickListener()...{
public void onClick(View v)...{
String result=HelloThreeB.this.i.getData().toString()+" And Two";
HelloThreeB.this.setResult(RESULT_OK,result);
finish();
}
});
TextView v = (TextView)findViewById(R.id.txt);
v.setText("Param is "+i.getData().toString());
}
在按鈕處理事件中,從Intent取出參數,處理一下再用setResult返回給前一個Activity即可。
編譯運行即可。
來源:http://www.sf.org.cn/Android/lumen/20977.html