Android-活動(Activity)Intent
稍微正常點的應用都應該不只有一個活動,通常都是有成打的活動,然後通過各種事件進行跳轉。連線起各種活動的橋樑,就是所謂的Intent。
什麼是Intent?
Intent是Android用來連線各個元件並且將元件進行j解耦的重要元件,比如指明當前元件的意圖,或者在元件之間傳遞資料。
Intent相當於一個媒婆,為兩個元件牽線搭橋,並且為他們之間的資訊交換提供了渠道。比如,有一個人(Activity)想找個白富美當老婆,他把這個“意圖”寫在了臉上,然後讓媒婆(Intent)去找找看,有沒有這麼個人是符合要求的。媒婆找了找,還真有一個符合條件的人,然後就把這倆人介紹到一起,並且為對方提供他們想了解的資料。
Intent也分為兩種:顯式Intent(點名道姓)和隱式Intent(條件篩選)。我們一個一個說。
顯式Intent
首先上程式碼:
因為我們要實現Activity的跳轉,所以我們要建立兩個活動才行:
1 public class FirstActivity extends AppCompatActivity //第一個活動 2 { 3 4 @Override 5 protected void onCreate(Bundle savedInstanceState) 6 { 7 super.onCreate(savedInstanceState);8 setContentView(R.layout.activity_main); 9 Button button1 = (Button) findViewById(R.id.button_1); 10 button1.setOnClickListener(new View.OnClickListener() 11 { 12 @Override 13 public void onClick(View v) 14 { 15 Intent intent = newIntent(FirstActivity.this, SecondActivity.class); 16 startActivity(intent); 17 } 18 }); 19 } 20 }
1 public class SecondActivity extends AppCompatActivity //第二個活動 2 { 3 4 @Override 5 protected void onCreate(Bundle savedInstanceState) 6 { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_second); 9 } 10 }
第一個活動對應的佈局檔案:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent"> 4 5 <Button 6 android:id="@+id/button_1" 7 android:layout_width="wrap_content" 8 android:layout_height="wrap_content" 9 android:text="This is Button 1" /> 10 </LinearLayout>
第二個佈局檔案沒寫什麼,就不放上來了。
我們分析下程式碼:
FirstActivity在Button的點選事件中定義了一個Intent(媒婆),這個Intent有很多建構函式的過載,我們這裡使用的是
Intent(Context packageContext,Class<?> cls);
這裡我們要傳入兩個引數:第一個是這個啟動活動的上下文(上下文的解釋看上一篇),第二個是我們這個Intent的“意圖”,也就是我們這個Intent想跳轉到哪裡。但是我們要注意,第一個傳入的是物件(.this),第二個是.class,傳入類檔案之後,虛擬機器會自動裝載類檔案。
接下來,我們的Intent已經準備妥當,我們還需要去啟動Intent。使用startActivity(Intent intent),傳入我們的Intent就可以發動“媒婆”,啟動目標活動了。
隱式Intent
顯示Intent好比是指明瞭要志玲做老婆,點名道姓,意圖明顯。而隱式Intent,是規定了條件,只有符合條件的才能被我接納。
要想能匹配得上,有兩部分要完全相同:action和category。
廢話不多說,上程式碼,首先是AndroidMainifest.xml(只貼出修改部分)
1 <activity android:name=".SecondActivity"> 2 <intent-filter> 3 <action android:name=".ACTION_START" /> 4 <category android:name="android.intent.category.DEFAULT" /> 5 </intent-filter> 6 </activity>
我們修改了SecondActivity的標籤,為它加入了action和catagory標籤。action標籤說明了我們這個活動可以響應哪個action。action表明了我們這個活動可以執行的動作,可以使用系統提供的(比如撥號ACTION_CALL),也可以自己定義。這裡我們是自己定義的;catagory包含了更加細節的一些資訊。
然後我們修改FirstActivity.java的程式碼
1 public class FirstActivity extends AppCompatActivity 2 { 3 @Override 4 protected void onCreate(Bundle savedInstanceState) 5 { 6 super.onCreate(savedInstanceState); 7 setContentView(R.layout.activity_main); 8 Button button1 = (Button) findViewById(R.id.button_1); 9 button1.setOnClickListener(new View.OnClickListener() 10 { 11 @Override 12 public void onClick(View v) 13 { 14 Intent intent = new Intent(".ACTION_START"); 15 startActivity(intent); 16 } 17 }); 18 } 19 }
我們修改了Intent的建構函式,直接傳入了action的字串,表明我們想啟動能響應.ACTION_START這個action的活動。但是,我們在這裡並沒有出現於category的相關宣告,是怎麼回事呢?
因為我們給SecondActivity傳入的是"android.intent.category.DEFAULT"這個引數,這是一個預設的catgory,在我們startActivity時會自動呼叫這個引數到我們的intent中。
我們啟動程式,效果與剛才的是一樣的。
當然,我們也可以指定多個category,但是隻能有一個action。
1 intent.addCategory(".MY_CATEGORY1"); 2 intent.addCategory(".MY_CATEGORY2");
這樣就可以為我們的intent新增category了。
但是我們的所有活動裡面必須有一個是能響應你這個intent的,否則程式會崩潰。
隱式Intent的更多用法
我們在平時使用別人家的app時一定有過這樣的體驗:點選一個連結,系統會提示你選擇哪一個瀏覽器開啟網頁。這些動作都是通過Intent來完成的。接下來我們看看Intent還有什麼新玩法。
修改程式碼如下:
1 @Override 2 public void onClick(View v) 3 { 4 Intent intent = new Intent(Intent.ACTION_VIEW); 5 intent.setData(Uri.parse("http://www.baidu.com")); 6 startActivity(intent); 7 }
我們這裡傳入的是"ACTION_VIEW"這個action,這是一個系統內建的action。然後我們呼叫intent的setData方法。這個方法是用來指定我們當前Intent操作的資料,它的引數是一個Uri物件。所以我們裡面使用Uri.parse來將一個網址解析成為了一個Uri物件(parse,分析的意思)。然後我們重新執行程式:
可以看到我們的程式成功響應了我們的請求,打開了我們指定的網頁。
那我們的程式能不能響應開啟網頁的請求呢?我們只要在相應的activity標籤中去新增屬性就可以了。
修改AndroidManifest.xml如下:
1 <activity android:name=".SecondActivity"> 2 <intent-filter tools:ignore="AppLinkUrlError"> 3 <action android:name="android.intent.action.VIEW" /> 4 <category android:name="android.intent.category.DEFAULT" /> 5 <data android:scheme="http" /> 6 </intent-filter> 7 </activity>
我們修改了SecondActivity的屬性,讓他能響應所有http協議的網址。並且修改了action為系統內建的action,它能響應Intent.ACTION_VIEW,也就是我們剛才傳入的那個值。
我們還能指定的data有:
android:scheme 指定資料的協議,如http;
android:host 指定資料的主機名,如www.baidu.com
android:port 指定埠,比如:8080,:80
還有很多,不常用的就不寫在這裡了。
我們點選FirstActivity的按鈕之後:
可以看到,我們的IntentDemo能夠響應網頁的請求了,就是因為我們在SecondActivity中添加了一個“可以響應http協議”的屬性。
除了網頁,我們還可以讓其響應撥號事件:
1 Intent intent = new Intent(Intent.ACTION_DIAL); 2 intent.setData(Uri.parse("tel:10010"));
使用Intent傳遞資料
傳遞資料給下一個活動
到目前為止,我們還只是使用Inten來跳轉活動。但是我們如果有需求,讓活動在跳轉的時候傳遞資料呢?
很簡單,Intent是一個橋樑,你把你想傳的放在橋上,然後讓另外一個人過來取不就行了嗎。Intent為我們提供了一個各式各樣的籃子,我們根據我們的需要,將資料放在籃子裡就行了。
上程式碼!
1 @Override 2 public void onClick(View v) 3 { 4 String data = "馬什麼梅?"; 5 Intent intent = new Intent(FirstActivity.this, SecondActivity.class); 6 intent.putExtra("my_data", data); 7 startActivity(intent); 8 }
我們定義了一個字串,用來作為傳遞的資料。(馬冬什麼?)然後我們使用的是顯式Intent,並使用putExtra(String name,DataType value)方法來傳值的(DataType代表很多資料型別)。
第一個引數,是這個資料的“鍵”。你可以理解為關鍵字,也可以簡單的理解這個資料的名字。你把資料放我這個大籃子裡面了,不得標示一下這個資料的身份嗎,否則到時候用找誰拿去啊。
第二個引數就是我們的資料了。
然後我們在SecondActivity中相應的去接收資料:
1 @Override 2 protected void onCreate(Bundle savedInstanceState) 3 { 4 super.onCreate(savedInstanceState); 5 setContentView(R.layout.activity_second); 6 Intent intent = getIntent(); 7 String data = intent.getStringExtra("my_data"); 8 Toast.makeText(SecondActivity.this, data, Toast.LENGTH_SHORT).show(); 9 }
我們定義了一個Intent,並用getIntent()方法來獲取到用來啟動這個activity的Intent。然後使用getStringExtra(String name)來獲取我們存在“籃子”裡面的字串,引數當然就是我們剛才設定的資料的名字(鍵)。為了展示是否成功,我就簡單的去Toast了一下。
可以看到,我們成功返回了資料。我們這裡傳的是字串,要是Boolean就是getExtraBoolean,其他的以此類推,傳的什麼型別就接什麼。
返回資料給上一個活動
我們傳遞資料給下一個活動是使用的Intent來暫存的,但是我們要是想直接返回上一個活動只需要按下返回鍵就可以了,並沒有什麼Intent參與其中。這時候我們的思路就要轉換一下了。你不主動給我?那好,我直接在啟動你的時候向你伸手要總行了吧!
修改FirstActivity的程式碼如下:
1 @Override 2 public void onClick(View v) 3 { 4 Intent intent = new Intent(FirstActivity.this, SecondActivity.class); 5 startActivityForResult(intent,1); 6 }
既然是張嘴要,就給在啟動的時候說明白了。使用startActivityForResult(Intent intent,int requestCode),第一個就是我們的Intent,第二個是請求碼。要是有很多資料返回來的話,我們要對他們進行區分,這就是請求碼的用意。
接下來就是SecondActivity:
1 @Override 2 public void onClick(View v) 3 { 4 Intent intent = new Intent(SecondActivity.this,FirstActivity.class); 5 intent.putExtra("data_return", "什麼冬梅?"); 6 setResult(RESULT_OK, intent);7 }
我們還是構建了一個Intent來跳轉到上一個活動。然後放一個字串,並使用setResult(int resultCode,Intent data)來向上一個活動傳值。第一個是結果值,一般使用RESULT_OK和RESULT_CANCELED兩個值,用來告訴上一個活動返回資料的處理結果。第二個就是我們的intent了。
我們既然要向上一個活動返回資料,就得有相應的措施來處理返回資料。
新增FirstActivity的程式碼:
1 @Override 2 protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) 3 { 4 switch (requestCode) 5 { 6 case 1: 7 if (resultCode == RESULT_OK) 8 Toast.makeText(FirstActivity.this, data.getStringExtra("data_return"), Toast.LENGTH_SHORT).show(); 9 break; 10 default: 11 } 12 }
我們重寫了FirstActivity的onActivityResult方法。這個方法接收三個引數,具體意義就不講了,都能看明白。
因為資料會有很多,所以我們第一件事就是去判斷資料來源,也就是我們的requestCode。因為如果有多個時間指向同一activity的話我們就必須分清資料從哪裡來。然後我們還需要去檢查結果碼,看看是不是成功了。
好了,這就是Intent的內容,對於我們初學者來說,這些內容很夠了。
菜鳥一個,多多指教!