Android 路由框架

參考文獻:java

superxlcr的ARouter學習筆記android

碼字農民工的文章git

繁華落盡666的文章程序員

本文主要介紹的知識點

  • 關於android路由框架解決的問題
  • android路由框架的使用(這裏只是介紹ARouter的使用)
  • 關於使用ARouter框架的注意事項
  • 總結

1.Android路由框架解決的問題

相信你們在工做中都會遇到這樣的問題,經過其餘App或者經過網頁跳轉到指定的本身的App或者跳轉到指定的頁面中去,通常都是在推送中或者經過Banner點擊以後的操做,通常的操做都是像下面這樣的github

  • 設置相應的intent-filter
<intent-filter>
	<action android:name="com.hejin.arouter.Main2Activity"/>
	<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
複製代碼
  • 經過Intent隱式跳轉到相應的Activity
Intent intent = new Intent();
	intent.setAction("com.hejin.arouter.Main2Activity");
	startActivity(intent);
複製代碼

其實這裏我要說明一下,若是你是正規的開發公司我以爲通常都不會這麼去寫,其實這個跳轉徹底能實現,可是通常正規的公司都會定一些協議和端口號,也就是說會添加scheme來指定一些數據的協議部分和path進行匹配,可是隨着時間的推移和團隊的擴大,會慢慢的暴露出不少問題:編程

  • 集中式的URL管理:談到集中式的管理,老是比較蛋疼,多人協同開發的時候,你們都去AndroidManifest.xml中定義各類IntentFilter,使用隱式Intent,最終發現AndroidManifest.xml中充斥着各類Schame,各類Path,須要常常解決Path重疊覆蓋、過多的Activity被導出,引起安全風險等問題
  • 可配置性較差:Manifest限制於xml格式,書寫麻煩,配置複雜,能夠自定義的東西也較少
  • 跨模塊沒法顯式依賴:在App小有規模的時候,咱們會對App作水平拆分,按照業務拆分紅多個子模塊,之間徹底解耦,經過打包流程控制App功能,這樣方便應對大團隊多人協做,互相邏輯不干擾,這時候只能依賴隱式Intent跳轉,書寫麻煩,成功與否難以控制。

尤爲是在項目演進的時候都會進行組件化開發,因此這裏網上有不少大神就研究出路由框架這麼一個東西,解決了上面的相應問題,這裏接觸的就是阿里巴巴開源的ARouter在GitHub上已經已經有3.+k的start了,相對來講應該比較穩定,因此讓咱們開始吧!api

2.ARouter的簡單使用

2.1首先是把ARouter引入到項目中去

  • 首先在在module中配置相應的參數
defaultConfig {
        .......
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [ moduleName : project.getName() ]
            }
        }
    }
複製代碼
  • 而後配置api和compiler(這個也是在module中)
dependencies {
    compile 'com.alibaba:arouter-api:x.x.x'
    annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'
    ...
}
複製代碼
  • 上面是github上面寫的內容,可是有一點他沒有寫,可是就是必定要在項目的gradle中添加下面這段代碼:
dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //路由須要
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
複製代碼

這句話必定要加上不然根本就跳轉不過去,具體爲何我還真是不知道.... 有了以上的內容就完成了基本的配置,就能夠進行相應的跳轉了...安全

2.2代碼中的簡單使用

  • 在Application中初始化ARouter
/*初始化路由框架*/
        ARouter.init(this);
複製代碼
  • 首先要在你要跳轉的Activity(或者說是目標的Activity)添加註釋
@Route(path = "XXX/XXX")
複製代碼

這裏面要注意兩點首先這個註解裏面的內容必須是二級菜單,這個在github上面有解釋,其次就是這個註解要寫在Activity的類上邊bash

  • 經過代碼進行跳轉(發起路由)
ARouter.getInstance().build("/XXX/XXX").navigation();
//跳轉中攜帶參數
ARouter.getInstance().build("/XXX/XXX")
             .withLong("key", "value")
             .withString("key", "value")
             .navigation
複製代碼

這裏面的參數要和你要跳轉的Activity註解中的參數保持一致,當你傳遞參數的時候,你直接經過Intent去取就能夠了.app

經過以上步驟就能實現基本的跳轉傳遞參數了,可是身爲有逼格的程序員咱們怎麼能這樣就知足了呢?

3.ARouter進階使用

3.1 利用Uri進行跳轉

Uri uri = Uri.parse("/test/activity");
        ARouter.getInstance()
                .build(uri)
                .navigation();
複製代碼

3.2傳遞參數的獲取問題

當你傳遞參數的時候你能夠經過Intent取獲取,固然也能夠經過相應的註解進行獲取,就像下面這樣:

@Autowired(name = "xxx")
public String text;
複製代碼

這裏呢要注意,修飾符必須是public而且key值要相互對應.還要在目標的Activtiy中添加**ARouter.getInstance().inject(this);**纔可使用相應的值,不然取值的時候會失敗,可是不會報空指針.

3.3關於轉場動畫的跳轉處理

有沒有想過,以前在Activity跳轉的時候可使用overridePendingTransition();,可是如今經過路由跳轉的話,沒有地方取設置動畫了,而後ARouter爲咱們想到了這個問題.

  • 舊動畫:使用withTransition方法便可(至關於以前的overridePendingTransition()方法設置)
ARouter.getInstance().build(path).withTransition(R.anim_slide_in,R.anim_slide_out);
複製代碼
  • 新動畫:使用withOptionsCompat方法便可(Android5.0新出的轉場動畫)
ActivityOptionsCompat compat = ActivityOptionsCompat.makeScaleUpAnimation(view, view.getWidth() / 2, view.getHeight() / 2, 0, 0);
ARouter.getInstance().build("path").withOptionsCompat(compat).navigation();
複製代碼

3.4ARouter處理跳轉過程的結果

ARouter可讓咱們處理跳轉過程的結果,什麼用呢?就是你找到目標以後要進行什麼操做.

ARouter.getInstance().build("/module/jumpTestActivity2").navigation(null,new NavigationCallback() {  
            @Override
            public void onFound(Postcard postcard) { 
            // 找到目標後進行的操做
            }
            
            @Override 
            public void onLost(Postcard postcard) {
            // 找不到目標進行的操做
            }
        });
複製代碼

補充說明: 在最新api中已是四個方法了!

ARouter.getInstance().build("/test/activity").navigation(this, new NavigationCallback() {
            @Override
            public void onFound(Postcard postcard) {
		//找到隊應的內容的時候
                Log.e("done", "onFound: ");
            }

            @Override
            public void onLost(Postcard postcard) {
		//沒有找到對應的內容的時候
                Log.e("done", "onLost: ");
            }

            @Override
            public void onArrival(Postcard postcard) {
		//跳轉成功
                Log.e("done", "onArrival: ");
            }

            @Override
            public void onInterrupt(Postcard postcard) {
		//攔截操做
                Log.e("done", "onInterrupt: ");
            }
        });
複製代碼

這裏能夠在onLost中去處理"位置頁面"的跳轉結果,好比升級APP之類的話術.

3.5攜帶結果的Activity

ARouter.getInstance().build("/test/activity").navigation(this,10);
複製代碼

後面那個參數就是請求碼,別的和以前的都同樣.

3.6組的概念

在ARouter中有個組的概念,什麼意思呢?就是在構建路由請求的時候,能夠指定分組. 其實這個分組原本就是有個你像path=/test/activity test就至關是分組,可是也可使用group進行分組,像下面這段代碼:

@Route(path = "/test/activity", group = "app")
複製代碼

這裏須要強調一下,若是你設置了相應的分組,那麼在進行跳轉的時候,必定要使用ARouter.getInstance().build(path, group)進行跳轉,不然沒法找到相應的跳轉

3.7重寫跳轉URL實現重定向

能夠從新定向你的URL地址

@Route(path = "/test/activity2")
public class PathReplaceServerImp implements PathReplaceService {
    @Override
    public String forString(String path) {

        path = "/test/activity2";
        return path;
    }

    @Override
    public Uri forUri(Uri uri) {
        return null;
    }

    @Override
    public void init(Context context) {
        Log.e("done", "init: 這裏是初始化的時候執行的方法");
    }
}
複製代碼

這裏說明一下:上面得path必定要加上一個任意項目中出現得註解便可,若是項目中沒有出現得話會報空指針異常的.經過上面的代碼,就能夠更改項目中跳轉時候的path和URL地址了.

3.8ARouter攔截器

ARouter的攔截器能夠在navigation的過程當中攔截請求,並進行一系列的處理 ,是一種AOP的編程模式(應用場景爲檢查登錄狀態等)要實現攔截器,首先咱們須要實現IInterceptor接口,並使用Interceptor註解標記咱們的攔截器,並傳入priority優先級參數(數字越小,優先級越高),其實攔截器就是實現了一個接口去進行回調的!

public class TestInterceotor implements IInterceptor {
    @Override
    public void process(Postcard postcard, final InterceptorCallback callback) {
        if (postcard.getPath().equals("/test/activity")) {
            callback.onContinue(postcard);
        } else {
            callback.onContinue(postcard);
        }
    }

    @Override
    public void init(Context context) {
        Log.e("done", "init: 初始化調用");
    }
}
複製代碼

這裏說明幾點內容:

  • 首先process這個方法是處理攔截內容的,這裏我判斷了一個相應的註解路由,若是跳轉的是相應的路徑,那麼進行攔截.
  • 其次callback.onContinue(postcard)這個要注意,這句話的含義就是交由路由去處理,若是這裏不寫這句話的話,路由就終止了.
  • init方法是全局只執行一次,這裏爲何這麼設計我也不知道,應該是用到相應的內容了吧!原諒我是一個菜鳥
  • 若是你想加入相應的等級的話在類的上面加入以下註解**@Interceptor(priority = 7)**其實就是設置攔截器等級的,這裏爲何又攔截器的等級呢?主要是爲了讓攔截器一級一級的向下傳遞.這樣就有了多級的攔截器.

上面的內容只是簡單的用到了攔截器,可是理解起來畢竟又一些晦澀,當直接說讓你實現登錄的攔截,你怎麼實現,開始的時候我也以爲簡單,可是當本身寫的時候,我發現這個問題真不是看上去那麼簡單.這裏我先把內容攔截器的代碼都放上,而後我在講解!

  • 首次跳轉的邏輯
ARouter.getInstance().build("/test/activity").navigation(this, new NavCallback() {
            @Override
            public void onArrival(Postcard postcard) {

            }

            @Override
            public void onInterrupt(Postcard postcard) {
                Log.e(TAG, "onInterrupt: 這個方法是攔截器執行以後才執行的");
            }
        });
複製代碼
  • 攔截器的代碼:
@Interceptor(priority = 7)
public class TestInterceotor implements IInterceptor {
    @Override
    public void process(Postcard postcard, final InterceptorCallback callback) {
        if (postcard.getPath().equals("/test/activity")) {
            Log.e("done", "process: main2Activity");
            if (APP.isLogin) {/*已經登錄*/
                callback.onContinue(postcard);
            } else {/*沒有登錄*/
                ARouter.getInstance().build("/test/activity2")
                        .withString("name", postcard.getPath()).navigation();
            }
            Log.e("done", "process: 執行完了");
        } else {
            Log.e("done", "process: 這個方法何時執行");
            callback.onContinue(postcard);
        }
    }

    @Override
    public void init(Context context) {
        Log.e("done", "init: 初始化調用");
    }
}
複製代碼
  • 模擬登錄的Activity
@Route(path = "/test/activity2")
public class Main3Activity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        ARouter.getInstance().inject(this);
    }

    public void click(View view) {
        APP.isLogin = true;
        ARouter.getInstance().build("/test/activity").navigation();
        finish();
    }
}
複製代碼

這裏第一次跳轉的時候,因爲攔截器使得沒有登錄的邏輯就跳轉到了登錄頁面,以後我在登錄頁面模擬了一次登錄的操做,而後關閉這個頁面以前,我又從新跳轉了目標頁面,此次因爲已經登錄了,因此會直接繼續執行跳轉了目標頁面.這裏說的挺簡單的,有一個回調我尚未搞清楚,onInterrupt這個回調以後有什麼用,其實這裏也能夠傳入一個字段,而後跳轉的時候直接傳入這個字段,這個字段主要是保存要跳轉的頁面的數據,以後就能直接跳轉了.這樣就解決了耦合的問題.

3.9在攔截器中添加額外的參數

@Route(path = "/test/activity", extras = 0;/*注意這裏是int類型的參數*/)
複製代碼

說明一下:這個是在目標的Activity頁面添加的額外參數,以後會在攔截器內生效.

總結

其實關於這個框架還有不少問題我沒有理解,可是基本的一些內容都已經講解了,其實接觸這個框架主要是當初看見組件化開發的時候,看到了這個框架,其實在項目中使用也能夠,總體管理了跳轉.寫的挺亂的,感謝你們抽出寶貴時間來閱讀,有什麼不對的地方但願指正.

相關文章
相關標籤/搜索