Intent ---> 一個萬能的信使

Intent的奧秘

Intent稱為信使簡直在形象不過了。
隨著Android開發(fā)經(jīng)驗的增長,慢慢隨著時間的積累,我們會很自然的發(fā)現(xiàn)一些讓人佩服的東西,Intent就是其中一個。
我現(xiàn)在看見這個關(guān)鍵字,腦子里立馬浮現(xiàn)出古代的信鴿、欽差。傳遞信息、傳遞動作。
今天我們就根據(jù)它的特性延伸一下,來解決項目中的需求。

Intent的應(yīng)用詳解

這塊是本文最關(guān)鍵,也是最基本的知識
不太明白的朋友我推薦一篇很詳細(xì)的博文

萬能信使的誕生

那現(xiàn)在就進(jìn)入主題吧。為什么這么叫呢?
先賣個關(guān)子!在這個產(chǎn)品橫行的時代,在他們的’督促‘下,我們程序員不停的在進(jìn)化。至少我們知
一下幾點:

  1. 代碼不能寫死,隨時準(zhǔn)備著改;
  2. 客戶端的功能最好能讓服務(wù)端控制;
  3. 隨時準(zhǔn)備重構(gòu)別人的代碼(已經(jīng)被產(chǎn)品送走了)

好了言歸正傳,我也是因為上面的第二個原因做了這個事情。
直接用需求來說:這個界面用native去寫,不用h5,但是我還要能在服務(wù)端控制這個頁面上的某些View的’行為’。
也就是說有一個按鈕,我可以在服務(wù)端去控制它打開一個新Activity,還是一個網(wǎng)頁,還是預(yù)先定義好的某種行為。

也就是在這個時候我發(fā)現(xiàn)了萬能的信使Intent,正好能解決這種問題。
同時我也說明一下,今天我只是講這種實現(xiàn)的方式,只是取其中的原理性東西來說。更多的idea,更多的需求,只希望你看完后能有所啟示吧。

Demo源碼

項目在Github上:GitHub
順便簡單介紹一下Demo:一次偶然的機(jī)會,扔物線的推薦下開始了使用Rxjava + Retrofit網(wǎng)絡(luò)庫,深深地迷上了它(我指的是它,而不是這個胖子,哈哈~~)
這些代碼是我從整個項目里面摘出來的,可能會有一些殘留,見諒哈!我盡量處理干凈。

萬能的Intent

先介紹Intent的跳轉(zhuǎn)規(guī)則:

/** 
 * 打電話
 * @param view 
 */
public void call(View view) {  
    Intent intent = new Intent(Intent.ACTION_CALL);  
    intent.setData(Uri.parse("tel:1234567890"));  
    startActivity(intent);  
} 
/** 
 * 打開指定網(wǎng)頁 
 * @param view 
 */  
public void invokeWebBrowser(View view) {  
    Intent intent = new Intent(Intent.ACTION_VIEW);  
    intent.setData(Uri.parse("http://www.google.com.hk"));  
    startActivity(intent);  
}

就上面這段代碼中intent.setData()的方法,里面需求傳入各種系統(tǒng)規(guī)定好的標(biāo)簽,按照這種規(guī)則去通過Uri.parse去按照規(guī)則解析,從而獲得這種行為動作。
那么我們?nèi)绾沃滥繕?biāo)是否接受這種前綴呢?這就需要看一下目標(biāo)中<data/>元素的匹配規(guī)則了。
在目標(biāo)<data/>標(biāo)簽中包含了以下幾種子元素,他們定義了url的匹配規(guī)則:
android:scheme 匹配url中的前綴,除了“http”、“https”、“tel”...之外,我們可以定義自己的前綴
android:host 匹配url中的主機(jī)名部分,如“google.com”,如果定義為“*”則表示任意主機(jī)名
android:port 匹配url中的端口
android:path 匹配url中的路徑
我們看下面的這兩塊代碼,這是和Android瀏覽器之間交互的規(guī)則

<activity android:name=".TestActivity">  
    <intent-filter>  
        <action android:name="com.scott.intent.action.TARGET"/>  
        <category android:name="android.intent.category.DEFAULT"/>  
        <data android:scheme="scott" android:host="com.scott.intent.data" android:port="9090" android:path="/test"/>  
    </intent-filter>  
</activity> 
public void gotoTestActivity(View view) {  
    Intent intent = new Intent("com.scott.intent.action.TARGET");  
    intent.setData(Uri.parse("scott://com.scott.intent.data:9090/test"));  
    startActivity(intent);  
} 

我們用Intent調(diào)系統(tǒng)打電話為例:

順序圖

這些信息的中的標(biāo)簽都是系統(tǒng)自己定義的,那么我們需要解決自己的需求,就要定義自己的規(guī)則。
下面我們一起來一步一定義我們自己的規(guī)則,來滿足我們的需求。如果上面的系統(tǒng)規(guī)則不明白,沒事。接著往下走,串起來就都明白了。

自定義規(guī)則

直接打開一個Activity

首先,我們看一下Intent的源碼,其中有一個parseUri方法。
里面寫的很清楚,系統(tǒng)定義的規(guī)則開頭是以android-app開頭的,并且是以end結(jié)尾

     *     <tr><td><code>android-app://com.example.app/http/example.com/foo?1234<br/>#Intent;action=com.example.MY_ACTION;end</code></td>
     *         <td><table style="margin:0;border:0;cellpadding:0;cellspacing:0">
     *             <tr><td>Action: </td><td><code>com.example.MY_ACTION</code></td></tr>
     *             <tr><td>Data: </td><td><code>http://example.com/foo?1234</code></td></tr>
     *             <tr><td>Package: </td><td><code>com.example.app</code></td></tr>
     *         </table></td>
     *     </tr>

這是源碼中的一條規(guī)則

android-app://com.example.app/http/example.com/foo?1234#Intent;action=com.example.MY_ACTION;end

android-app:這部分表示系統(tǒng)規(guī)則的前綴,所以在我們自己定義規(guī)則時需要將系統(tǒng)的屏蔽掉,以免沖突,所以我們現(xiàn)在用intent做以區(qū)分,并且表明這個規(guī)則是要生成Intent
#Intent而這一句則是規(guī)則真正的開始,源碼中的一句i = uri.lastIndexOf("#");也就是從#開始到end才是我們需要自己定義的規(guī)則
Action就是我們要做的事,但是我們今天的需求是跳轉(zhuǎn)行為,所以這個用component

好了,介紹完系統(tǒng)的規(guī)則,來看一下打開我們定義的某個Activity的規(guī)則

"intent:#Intent;component=com.alex.alexintentdemo/.ui.TestActivity;end"

component=com.alex.alexintentdemo/.ui.TestActivity這個我相信大家看了絕對眼熟,沒錯,這個就是系統(tǒng)的規(guī)則,在New IntentsetComponent然后startActivity時,需要填寫的,告訴系統(tǒng)我要打開那個Activity

好了,既然規(guī)則寫好了,那么接下來我們再根據(jù)規(guī)則生成Intent,去調(diào)用

剛才講的這一整體部分最好結(jié)合代碼去看,UriUtils解析自定義Uri的類

直接打開一個接受參數(shù)的Activity

這種直接打開Activity有點太low了,接下來,我們要解決怎么打開一個接受參數(shù)的Activity
首先,我們看一下系統(tǒng)的支持參數(shù)的源代碼

String key = Uri.decode(uri.substring(i + 2, eq));
if (uri.startsWith("S.", i)) {
        intent.putExtra(key, value);
  } else if (uri.startsWith("B.", i)) {
      intent.putExtra(key, Boolean.parseBoolean(value));
  } else if (uri.startsWith("b.", i)) {
      intent.putExtra(key, Byte.parseByte(value));
  } else if (uri.startsWith("c.", i)) {
      intent.putExtra(key, value.charAt(0));
  } else if (uri.startsWith("d.", i)) {
      intent.putExtra(key, Double.parseDouble(value));
  } else if (uri.startsWith("f.", i)) {
      intent.putExtra(key, Float.parseFloat(value));
  } else if (uri.startsWith("i.", i)) {
      intent.putExtra(key, Integer.parseInt(value));
  } else if (uri.startsWith("l.", i)) {
      intent.putExtra(key, Long.parseLong(value));
  } else if (uri.startsWith("s.", i)) {
      intent.putExtra(key, Short.parseShort(value));
    } else throw new URISyntaxException(uri, "unknown EXTRA type", i);

這樣我們可以看出,所有的基本類型都支持,并且有一套完整的書寫規(guī)則:
我們常用的有下面三個,其他的都支持

 S.xxx=[string];//字符串類型
 B.xxx=[boolean];//布爾型
 i.xxx=[int];//整型

所以我們傳參數(shù)的規(guī)則如下:

intent:#Intent;component=com.alex.alexintentdemo/.ui.Test2Activity;B.flag=true;S.name=大家好;i.code=1221;end

特別提示:每一條指令之間用區(qū)分

直接打開Http/Https鏈接

這個就相對簡單了,看源碼,只是在Uri解析的時候區(qū)分一下http/https的前綴。
規(guī)則直接下發(fā)鏈接就可以了。

服務(wù)端控制行為

只要在init或者開發(fā)App的時候從服務(wù)端取下這些規(guī)則,在點擊按鈕,或者需要出發(fā)的時候調(diào)一下CommonUtils.jumpWithUri()就可以了

CommonUtils.jumpWithUri(MainActivity.this,“rule”);

可擴(kuò)展的需求

今天在這里只是自定義了打開Activity。其實,其余的方式都是一樣的,只要明白了這一點就能相通了。
我在這里先列出幾個:

  1. 打開Fragment;
  2. WebView傳參數(shù);
  3. 彈出Toseat;
  4. 等等,太多了,只要你想的到,只要你的規(guī)則能寫好,一切都不是事。

后續(xù)我會慢慢給Demo里完善這些東西

結(jié)束

很感謝大家能閱讀完這篇博文,寫的不合理、不行清楚、有錯誤,請評論指出,我們共同學(xué)習(xí)成長。

版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請注明出處。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容