淺談關于Android路由的實現(xiàn)
先說一下背景,目前有需求從外部包括其他應用和WEB跳轉到我們自己的APP,就這么個簡單的需求……
要實現(xiàn)這種外部跳轉的功能,我們可以理解為打算跳轉的一方有多少方式通知到APP進行相對的響應行為。所以,如果是應用之間的跳轉,則有多種,你可以直接通過包名和具體的類名去打開已經(jīng)exported=true的Activity,又或者直接通過Android的廣播通知進行相關的APP,又或者通過自定義的URL去打開應用。但是如果涉及到Web打開外部應用的話,目前只有一種辦法,那就是自定義應用的URL進行攔截,系統(tǒng)會自動調起相應的組件響應這個URL。
但是,要做這種需求,很少會僅僅是完成對外部的支持而已,通常也要進行一定的內部邏輯跳轉映射。所以要做這種需求通常分為兩個種,一種是對內的(應用內部自己的跳轉邏輯),一種對外的(其他應用以及Web跳轉邏輯)。
我們先說一下對外的情形,由于考慮到統(tǒng)一性,我們目前只有URL這種手段可以使用了。下面我們一一來說
1、對外跳轉說明
1.1、關于URL的說明。
首先,我們得了解一下URL,這里直接引用 https://en.wikipedia.org/wiki/URL 的說明。為了方便說明,我稍稍修改一下,大概的格式如下:
scheme:[//host[:port]][/path][?query][#fragment]
首先,scheme是必須的,其他的都是不必須的,但是對于跳轉來說,顯然不可能,因為你要從這個url中取出跳轉相關的信息。所以,通常一定要要有host和query。我們經(jīng)??吹揭恍╅_源的路由實現(xiàn),都會支持所謂的restful風格的url,比如:wytings://app/{city}/{id} ,但我個人認為是沒有必要的。主要是因為這種外部跳轉的行為,通常量比較少,其次應該盡量統(tǒng)一而且方便,而不是為了追求各種技術炫酷…我刻意看了微信的scheme就甚合我意~都是類似于這種格式:weixin://qrscan?a=1&b=2
我們進行一下歸納,就可以進行應用的URL定義了,首先scheme是必須項,看個人和公司要求,比如接下來要舉的例子,我定義的scheme為wytings,然后支持的模塊都集中于host字段,具體參數(shù)則全部通過query補充。比如:wytings://user?uin=10000 打開個人頁面,wytings://stockDetail?marketcode=hk&stockcode=00376 打開股票詳情頁面等等。
要是對外部的支持,通常我們不會對每一個要支持的Activity都進行相應的intent-filter限制,而是定義一個公共的Activity進行所有外部請求的攔截形如:
<activity android:name=".activity.SchemeFilterActivity" android:exported="true" android:theme="@android:style/Theme.NoDisplay"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="wytings" /> </intent-filter> <intent-filter android:autoVerify="true" tools:targetApi="m"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:host="native.app.wytings.com" android:scheme="http" /> <data android:host="native.app.wytings.com" android:scheme="https" /> </intent-filter> </activity>
我們對這個Activity的定義進行一下說明:
a、android:exported這個屬性其默認是false就是對外不開放,我們必須要設置為true,因為我們要讓外部能夠對其進行訪問。
b、android:theme="@android:style/Theme.NoDisplay" 由于是作為攔截的Activity,所以,沒必要展示,但是這個NoDisplay的theme要求必須在onResume前finish掉Activity,否則要報錯。
c、第一個intent-filter自定義scheme為wytings,也就是攔截該類URL。
d、第二個scheme為http,但是加了特別的host=nativ.app.wytings.com,進一步詳細攔截url為:http://nativ.app.wytings.com 的url。為什么要攔截這種url,通常情況下不用,但是特殊情況下,有時候自定義的scheme可能失效,所以而外再加層保障,當然,也要與調用方預定好url格式,比如:http://nativ.app.wytings.com/stockDetail?marketCode=hk&stockCode=00376,由于host已經(jīng)被定義為別的,所以我們把具體模塊定義在path里面,參數(shù)依然保留在query中。
再來看看SchemeFilterActivity的實現(xiàn)情況:
/** * Created by rex on 06/10/2017. * * @author wytings@gmail.com */ public class SchemeFilterActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Uri uri = getIntent().getData(); Log.i("wytings", "uri = " + uri); String scheme = uri.getScheme(); if ("http".equals(scheme) || "https".equals(scheme)) { String routeModule = uri.getLastPathSegment(); if (!TextUtils.isEmpty(routeModule)) { RouteManager.getInstance().build(routeModule + "?" + uri.getQuery()).go(this); } } else { RouteManager.getInstance().build(uri.toString()).go(this); } finish(); } }
大體就是攔截,然后通過內部的RouteManager進行解析處理跳轉。RouteManager怎么處理和實現(xiàn)就太細節(jié)了,總的來說,這個Manager的職責就是把URL翻譯成具體的Intent,然后啟動相應的Activity。有興趣的同學可以自己去看看本篇文章的所有源碼:https://github.com/wytings/AndroidRoute
2、對內跳轉說明
由于是應用內的實現(xiàn),所以基本上,你想怎么實現(xiàn)就怎么實現(xiàn)。但是,無論多么變幻莫測,都繞不開一個核心那就是建立路由映射關系,打開相關頁面,取出請求參數(shù)這三大步驟。我們逐個來分析一下。
2.1、建立路由映射關系
這個是為了能夠知道特定的url到底應該展示哪個頁面。通常建立一個Map,然后查找。
2.3、打開相關頁面
在Android中,打開一個頁面總是有自己的一套邏輯,系統(tǒng)那一套則是通過Intent去啟動相應的組件展示。
2.4、取出參數(shù)
這個步驟,還是基于系統(tǒng)的Intent方式,要通過intent.getXXXExtra來取出相關參數(shù)。
這么一看好像,也沒什么難度。也確實沒什么難度,就單純實現(xiàn)功能來說。那難點在哪呢?難點在于你決定使用注解去做這件事……為什么要用注解?因為為了哪一丁點潔癖,解藕的潔癖。結果掉進坑里了…
用注解理論上,也還好,遍歷反射嘛,而且我個人測試了一下,就目前的機器真的感受不出來。當然再怎么樣,也沒在編譯時直接生成相關代碼來得快倒是真的……
于是乎,進入第三個大難題,那就是進行編譯時生成代碼,類似于ButterKnife一樣,在編譯期就生成相關代碼,而不是在運行時通過反射來給變量賦值。
這里就涉及到一個東西,那就是Java 的 AbstractProcessor,這個類是在編譯時生成代碼最關鍵的類。要講解這個得再開一篇《關于Java注解實現(xiàn)編譯時生成代碼》的文章了。同學們可以網(wǎng)上搜索一下基本知識,然后再看這個項目中的代碼,我自己也看了很多關于注解的文章,但是很遺憾,我沒看到哪篇是值得捧的,同樣也沒看到那篇值得噴的……我現(xiàn)在也沒時間專門寫篇關于注解的文章,但是可以給個方向,那就是先學會調試,AnnotatioProcessor的調試,跟普通java調試有點區(qū)別(自己google一下),然后就可以自己摸索了。另外,我審視了一下,我寫的Annotation compiler還是蠻清晰的,你也可以試著看看。
最后,再說一遍,項目地址:AndroidRoute
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Android實現(xiàn)Gesture手勢識別用法分析
這篇文章主要介紹了Android實現(xiàn)Gesture手勢識別用法,結合實例形式較為詳細的分析了Android基于Gesture實現(xiàn)手勢識別的原理與具體實現(xiàn)技巧,需要的朋友可以參考下2016-09-09XrecyclerView實現(xiàn)加載數(shù)據(jù)和切換不同布局
這篇文章主要為大家詳細介紹了XrecyclerView實現(xiàn)加載數(shù)據(jù)、切換不同布局功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12Android提高之AudioRecord實現(xiàn)助聽器的方法
這篇文章主要介紹了Android中AudioRecord實現(xiàn)助聽器的方法,對進行Android項目開發(fā)有一定的借鑒價值,需要的朋友可以參考下2014-08-08Android 8.0 讀取內部和外部存儲以及外置SDcard的方法
今天小編就為大家分享一篇Android 8.0 讀取內部和外部存儲以及外置SDcard的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08Android自定義View實現(xiàn)球形動態(tài)加速球
這篇文章主要為大家詳細介紹了Android自定義View實現(xiàn)球形動態(tài)加速球,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-06-06Android實現(xiàn)左上角(其他邊角)傾斜的標簽(環(huán)繞效果)效果
這篇文章主要介紹了Android實現(xiàn)左上角(其他邊角)傾斜的標簽(環(huán)繞效果)效果,本文通過圖文實例代碼相結合的形式給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10