android菜鳥學習筆記11----Intent的兩點補充,androidintent
關於Intent的兩點補充:
1.隱式Intent啟動組件,會有一個Intent解析的過程,若找不到能夠處理該Intent的組件,程式就會異常終止。一個合理的做法是,在使用Intent執行個體啟動組件如:startActivity(intent)之前,最好能判斷一下該調用能否解析為一個Activity。為了實現該功能,Intent提供了一個方法:
ComponentName resolveActivity(PackageManager pm) :該方法接收一個包管理器對象作為參數,通過尋找該包管理器,返回能夠處理該Intent的Activity的Component對象,沒有找到能處理該Inent的組件時則返回null。
Intent intent1 = new Intent(); intent1.setAction(Intent.ACTION_VIEW); intent1.setType("text/html"); Log.i("tag",intent1.toString()); ComponentName resolveActivity = intent1.resolveActivity(getPackageManager()); Log.i("tag",resolveActivity.getClassName()); Log.i("tag",resolveActivity.getPackageName()); Log.i("tag",resolveActivity.toString()); startActivity(intent1);
NormalActivity中配置<intent-filter>
1 <activity android:name=".NormalActivity"> 2 3 <intent-filter > 4 5 <action android:name="android.intent.action.VIEW"/> 6 7 <category android:name="android.intent.category.DEFAULT"/> 8 9 <data android:mimeType="text/html"/>10 11 </intent-filter>12 13 </activity>
運行資訊:
可見解析到cn.csc.lifecycle.NormalActivity能夠處理該Intent。
若找不到能夠處理該Intent的組件時,會返回null,所以,安全的啟動Activity的做法是:
1 if(intent1.resolveActivity(getPackageManager())!=null){2 3 startActivity(intent1);4 5 }
當然,可以加上找不到能處理intent1的組件的提示資訊等。
注意,若用多個組件都能處理該Intent執行個體時,如:
1 Intent intent1 = new Intent(); 2 3 intent1.setAction(Intent.ACTION_VIEW); 4 5 intent1.setData(Uri.parse("http://www.baidu.com")); 6 7 Log.i("tag",intent1.toString()); 8 9 ComponentName resolveActivity = intent1.resolveActivity(getPackageManager());10 11 Log.i("tag",resolveActivity.toString());12 13 startActivity(intent1);
1 <activity android:name=".NormalActivity"> 2 3 <intent-filter > 4 5 <action android:name="android.intent.action.VIEW"/> 6 7 <category android:name="android.intent.category.DEFAULT"/> 8 9 <data android:scheme="http"/>10 11 </intent-filter>12 13 </activity>
此時,瀏覽器和NormalActivity都能處理該Intent執行個體。
運行效果:
返回的Component資訊為:
這個ResolverActivity其實就是一個選擇開啟程式的對話方塊,當有多個組件能處理Intent執行個體,但是沒有設定預設的處理常式時,就會交由ResolverActivty來處理,而ResolverActivity的做法就是把所有能處理的都顯示在一個列表中,由使用者決定採用哪個來處理。當我們勾選了下面的use by default for this action時,之後選擇的組件將會作為該Intent的預設處理常式,該設定會儲存在手機或者模擬器中,下次在出現該Intent時,直接使用設定的預設組件去處理,而不再轉到ResolverActivity。
如,這裡我選擇了Browser作為預設處理常式,下次再啟動改程式,輸出的運行資訊:
2.關於使用Intent在Activity之間傳遞資料,在之前都是傳遞些內建類型的資料,若想傳遞自訂類型的資料,應該怎麼辦呢?
注意到在Intent中有下面兩對方法:
Serializable getSerializableExtra(String name)
Intent putExtra(String name, Serializable value)
放入/擷取Serializable類型的值。
<T extends Parcelable> T getParcelableExtra(String name)
Intent putExtra(String name, Parcelable value)
放入/擷取Parcelable類型的值。
Serializable和Parcelable都是介面,即要想使用Intent傳遞自訂類型的資料,則自訂類型的資料應當事先Serializable介面或者Parcelable介面。
Serializable介面:
java.io.Serializable是一個空的起到標記作用的介面。標記實現該介面,只需要在類定義時聲明實現該介面即可。實現該介面的類表明能夠被序列化和還原序列化,對大多數的類來說已然足夠了,當然,若想更細粒度的操縱序列化過程,可以實現下面這兩個方法:
private void writeObject(java.io.ObjectOutputStream out) throws IOException
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
一般情況下,都用不到的。
這裡簡單聲明實現該介面,如:
1 import java.io.Serializable; 2 3 4 5 public class MyData implements Serializable { 6 7 private String stringData; 8 9 private int intData;10 11 public MyData(String stringData, int intData) {12 13 super();14 15 this.stringData = stringData;16 17 this.intData = intData;18 19 }20 21 public String getStringData() {22 23 return stringData;24 25 }26 27 public void setStringData(String stringData) {28 29 this.stringData = stringData;30 31 }32 33 public int getIntData() {34 35 return intData;36 37 }38 39 public void setIntData(int intData) {40 41 this.intData = intData;42 43 }44 45 }
之後,便可以傳遞MyData類型資料了:
1 MyData data1 = new MyData(“aaa”,111);2 3 Intent intent1 = new Intent();4 5 intent1.putExtra(“mydata”, data1);
取得該資料:
1 MyData data1 = (MyData)getIntent.getSerializableExtra(“data1”);
Parcelable介面:相比Serializable要複雜一點,需要實現裡面的抽象方法。
android.os.Parcelable介面,協助文檔中,有一個典型的實現例子如下,可以用作參考,自己實現該介面時,模仿即可:
1 public class MyParcelable implements Parcelable { 2 3 private int mData; 4 5 public int describeContents() { 6 7 return 0; 8 9 } 10 11 public void writeToParcel(Parcel out, int flags) {12 13 out.writeInt(mData); 14 15 } 16 17 public static final Parcelable.Creator<MyParcelable> CREATOR 18 19 = new Parcelable.Creator<MyParcelable>() { 20 21 public MyParcelable createFromParcel(Parcel in) {22 23 return new MyParcelable(in); 24 25 } 26 27 public MyParcelable[] newArray(int size) { 28 29 return new MyParcelable[size]; 30 31 } 32 33 }; 34 35 private MyParcelable(Parcel in) { 36 37 mData = in.readInt(); 38 39 }40 41 }
定義各種內建類型的資料,然後在writeToParcel分別根據不同的類型調用對應類型的
out.writeXXX(mData);在構造方法中,分別調用in.readXX()即可。
然後就可以調用Intent putExtra(String name, Parcelable value)去放入該自訂類型資料,調用<T extends Parcelable> T getParcelableExtra(String name)擷取該自訂類型資料。