溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何搭建Alibaba-ARouter中的Android頁面路由框架

發(fā)布時間:2021-09-16 09:35:18 來源:億速云 閱讀:149 作者:柒染 欄目:移動開發(fā)

這篇文章將為大家詳細講解有關如何搭建Alibaba-ARouter中的Android頁面路由框架,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

開發(fā)一款App,總會遇到各種各樣的需求和業(yè)務,這時候選擇一個簡單好用的輪子,就可以事半功倍

前言

  Intent intent = new Intent(mContext, XxxActivity.class);
  intent.putExtra("key","value");
  startActivity(intent);

  Intent intent = new Intent(mContext, XxxActivity.class);
  intent.putExtra("key","value");
  startActivityForResult(intent, 666);

上面一段代碼,在Android開發(fā)中,最常見也是最常用的功能就是頁面的跳轉,我們經(jīng)常需要面對從瀏覽器或者其他App跳轉到自己App中頁面的需求,不過就算是簡簡單單的頁面跳轉,隨著時間的推移,也會遇到一些問題:

  1. 集中式的URL管理:談到集中式的管理,總是比較蛋疼,多人協(xié)同開發(fā)的時候,大家都去AndroidManifest.xml中定義各種IntentFilter,使用隱式Intent,最終發(fā)現(xiàn)AndroidManifest.xml中充斥著各種Schame,各種Path,需要經(jīng)常解決Path重疊覆蓋、過多的Activity被導出,引發(fā)安全風險等問題

  2. 可配置性較差:Manifest限制于xml格式,書寫麻煩,配置復雜,可以自定義的東西也較少

  3. 跳轉過程中無法插手:直接通過Intent的方式跳轉,跳轉過程開發(fā)者無法干預,一些面向切面的事情難以實施,比方說登錄、埋點這種非常通用的邏輯,在每個子頁面中判斷又很不合理,畢竟activity已經(jīng)實例化了

  4. 跨模塊無法顯式依賴:在App小有規(guī)模的時候,我們會對App做水平拆分,按照業(yè)務拆分成多個子模塊,之間完全解耦,通過打包流程控制App功能,這樣方便應對大團隊多人協(xié)作,互相邏輯不干擾,這時候只能依賴隱式Intent跳轉,書寫麻煩,成功與否難以控制。

另一個輪子

為了解決以上問題,我們需要一款能夠解耦、簡單、功能多、定制性較強、支持攔截邏輯的路由組件:我們選擇了Alibaba的ARouter。

一、功能介紹

  1. 支持直接解析URL進行跳轉、參數(shù)按類型解析到Bundle,支持Java基本類型(*)

  2. 支持應用內(nèi)的標準頁面跳轉,API接近Android原生接口

  3. 支持多模塊工程中使用,允許分別打包,包結構符合Android包規(guī)范即可(*)

  4. 支持跳轉過程中插入自定義攔截邏輯,自定義攔截順序(*)

  5. 支持服務托管,通過ByName,ByType兩種方式獲取服務實例,方便面向接口開發(fā)與跨模塊調(diào)用解耦(*)

  6. 映射關系按組分類、多級管理,按需初始化,減少內(nèi)存占用提高查詢效率(*)

  7. 支持用戶指定全局降級策略

  8. 支持獲取單次跳轉結果

  9. 豐富的API和可定制性

  10. 被ARouter管理的頁面、攔截器、服務均無需主動注冊到ARouter,被動發(fā)現(xiàn)

  11. 支持Android N推出的Jack編譯鏈

二、不支持的功能

  1. 自定義URL解析規(guī)則(考慮支持)

  2. 不能動態(tài)加載代碼模塊和添加路由規(guī)則(考慮支持)

  3. 多路徑支持(不想支持,貌似是導致各種混亂的起因)

  4. 生成映射關系文檔(考慮支持)

三、典型應用場景

  1. 從外部URL映射到內(nèi)部頁面,以及參數(shù)傳遞與解析

  2. 跨模塊頁面跳轉,模塊間解耦

  3. 攔截跳轉過程,處理登陸、埋點等邏輯

  4. 跨模塊API調(diào)用,模塊間解耦(注冊ARouter服務的形式,通過接口互相調(diào)用)

四、基礎功能

添加依賴和配置

apply plugin: 'com.neenbedankt.android-apt'

 buildscript {
  repositories {
   jcenter()
  }
  dependencies {
   classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
  }
 }

 apt {
  arguments {
   moduleName project.getName();
  }
 }

 dependencies {
  apt 'com.alibaba:arouter-compiler:x.x.x'
  compile 'com.alibaba:arouter-api:x.x.x'
  ...
 }

添加注解

 // 在支持路由的頁面、服務上添加注解(必選)
 // 這是最小化配置,后面有詳細配置
 @Route(path = "/test/1")
 public class YourActivity extend Activity {
  ...
 }

初始化SDK

 ARouter.init(mApplication); // 盡可能早,推薦在Application中初始化

發(fā)起路由操作

 // 1. 應用內(nèi)簡單的跳轉(通過URL跳轉在'中階使用'中)
 ARouter.getInstance().build("/test/1").navigation();

 // 2. 跳轉并攜帶參數(shù)
 ARouter.getInstance().build("/test/1")
    .withLong("key1", 666L)
    .withString("key3", "888")
    .navigation();

添加混淆規(guī)則(如果使用了Proguard)

 -keep public class com.alibaba.android.arouter.routes.**{*;}

五、進階用法

通過URL跳轉

 // 新建一個Activity用于監(jiān)聽Schame事件
 // 監(jiān)聽到Schame事件之后直接傳遞給ARouter即可
 // 也可以做一些自定義玩法,比方說改改URL之類的
 // http://www.example.com/test/1
 public class SchameFilterActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);

   // 外面用戶點擊的URL
   Uri uri = getIntent().getData();
   // 直接傳遞給ARouter即可
   ARouter.getInstance().build(uri).navigation();
   finish();
  }
 }

 // AndroidManifest.xml 中 的參考配置
 <activity android:name=".activity.SchameFilterActivity">
   <!-- Schame -->
   <intent-filter>
    <data
     android:host="m.aliyun.com"
     android:scheme="arouter"/>

    <action android:name="android.intent.action.VIEW"/>

    <category android:name="android.intent.category.DEFAULT"/>
    <category android:name="android.intent.category.BROWSABLE"/>
   </intent-filter>

   <!-- App Links -->
   <intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW"/>

    <category android:name="android.intent.category.DEFAULT"/>
    <category android:name="android.intent.category.BROWSABLE"/>

    <data
     android:host="m.aliyun.com"
     android:scheme="http"/>
    <data
     android:host="m.aliyun.com"
     android:scheme="https"/>
   </intent-filter>
 </activity>

使用ARouter協(xié)助解析參數(shù)類型

 // URL中的參數(shù)會默認以String的形式保存在Bundle中
 // 如果希望ARouter協(xié)助解析參數(shù)(按照不同類型保存進Bundle中)
 // 只需要在需要解析的參數(shù)上添加 @Param 注解
 @Route(path = "/test/1")
 public class Test1Activity extends Activity {
  @Param     // 聲明之后,ARouter會從URL中解析對應名字的參數(shù),并按照類型存入Bundle
  public String name;
  @Param
  private int age;
  @Param(name = "girl") // 可以通過name來映射URL中的不同參數(shù)
  private boolean boy;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);

   name = getIntent().getStringExtra("name");
   age = getIntent().getIntExtra("age", -1);
   boy = getIntent().getBooleanExtra("girl", false); // 注意:使用映射之后,要從Girl中獲取,而不是boy
  }
 }

開啟ARouter參數(shù)自動注入(實驗性功能,不建議使用,正在開發(fā)保護策略)

 // 首先在Application中重寫 attachBaseContext方法,并加入ARouter.attachBaseContext();
 @Override
 protected void attachBaseContext(Context base) {
 super.attachBaseContext(base);

 ARouter.attachBaseContext();
 }

 // 設置ARouter的時候,開啟自動注入
 ARouter.enableAutoInject();

 // 至此,Activity中的屬性,將會由ARouter自動注入,無需 getIntent().getStringExtra("xxx")等等

聲明攔截器(攔截跳轉過程,面向切面搞事情)

 // 比較經(jīng)典的應用就是在跳轉過程中處理登陸事件,這樣就不需要在目標頁重復做登陸檢查

 // 攔截器會在跳轉之間執(zhí)行,多個攔截器會按優(yōu)先級順序依次執(zhí)行
 @Interceptor(priority = 666, name = "測試用攔截器")
 public class TestInterceptor implements IInterceptor {
  /**
  * The operation of this interceptor.
  *
  * @param postcard meta
  * @param callback cb
  */
  @Override
  public void process(Postcard postcard, InterceptorCallback callback) {
   ...

   callback.onContinue(postcard); // 處理完成,交還控制權
   // callback.onInterrupt(new RuntimeException("我覺得有點異常"));  // 覺得有問題,中斷路由流程

   // 以上兩種至少需要調(diào)用其中一種,否則會超時跳過
  }

  /**
  * Do your init work in this method, it well be call when processor has been load.
  *
  * @param context ctx
  */
  @Override
  public void init(Context context) {

  }
 }

處理跳轉結果

 // 通過兩個參數(shù)的navigation方法,可以獲取單次跳轉的結果
 ARouter.getInstance().build("/test/1").navigation(this, new NavigationCallback() {
  @Override
  public void onFound(Postcard postcard) {
   ...
  }

  @Override
  public void onLost(Postcard postcard) {
   ...
  }
 });

自定義全局降級策略

  // 實現(xiàn)DegradeService接口,并加上一個Path內(nèi)容任意的注解即可
 @Route(path = "/xxx/xxx") // 必須標明注解
  public class DegradeServiceImpl implements DegradeService {
  /**
  * Router has lost.
  *
  * @param postcard meta
  */
  @Override
  public void onLost(Context context, Postcard postcard) {
    // do something.
  }

  /**
  * Do your init work in this method, it well be call when processor has been load.
  *
  * @param context ctx
  */
  @Override
  public void init(Context context) {

  }
  }

為目標頁面聲明更多信息

 // 我們經(jīng)常需要在目標頁面中配置一些屬性,比方說"是否需要登陸"之類的
 // 可以通過 Route 注解中的 extras 屬性進行擴展,這個屬性是一個 int值,換句話說,單個int有4字節(jié),也就是32位,可以配置32個開關
 // 剩下的可以自行發(fā)揮,通過字節(jié)操作可以標識32個開關
 @Route(path = "/test/1", extras = Consts.XXXX)

使用ARouter管理服務(一) 暴露服務

 /**
 * 聲明接口
 */
 public interface IService extends IProvider {
  String hello(String name);
 }

 /**
 * 實現(xiàn)接口
 */
 @Route(path = "/service/1", name = "測試服務")
 public class ServiceImpl implements IService {

  @Override
  public String hello(String name) {
   return "hello, " + name;
  }

  /**
  * Do your init work in this method, it well be call when processor has been load.
  *
  * @param context ctx
  */
  @Override
  public void init(Context context) {

  }
 }

使用ARouter管理服務(二) 發(fā)現(xiàn)服務

1. 可以通過兩種API來獲取Service,分別是ByName、ByType

IService service = ARouter.getInstance().navigation(IService.class); // ByType
 IService service = (IService) ARouter.getInstance().build("/service/1").navigation(); // ByName

 service.hello("zz");

2. 注意:推薦使用ByName方式獲取Service,ByType這種方式寫起來比較方便,但如果存在多實現(xiàn)的情況時,SDK不保證能獲取到你想要的實現(xiàn)

使用ARouter管理服務(三) 管理依賴

可以通過ARouter service包裝您的業(yè)務邏輯或者sdk,在service的init方法中初始化您的sdk,不同的sdk使用ARouter的service進行調(diào)用,每一個service在第一次使用的時候會被初始化,即調(diào)用init方法。

這樣就可以告別各種亂七八糟的依賴關系的梳理,只要能調(diào)用到這個service,那么這個service中所包含的sdk等就已經(jīng)被初始化過了,完全不需要關心各個sdk的初始化順序。

六、更多功能

初始化中的其他設置

 ARouter.openLog(); // 開啟日志
 ARouter.printStackTrace(); // 打印日志的時候打印線程堆棧

詳細的API說明

 // 構建標準的路由請求
 ARouter.getInstance().build("/home/main").navigation();

 // 構建標準的路由請求,并指定分組
 ARouter.getInstance().build("/home/main", "ap").navigation();

 // 構建標準的路由請求,通過Uri直接解析
 Uri uri;
 ARouter.getInstance().build(uri).navigation();

 // 構建標準的路由請求,startActivityForResult
 // navigation的第一個參數(shù)必須是Activity,第二個參數(shù)則是RequestCode
 ARouter.getInstance().build("/home/main", "ap").navigation(this, 5);

 // 直接傳遞Bundle
 Bundle params = new Bundle();
 ARouter.getInstance()
    .build("/home/main")
    .with(params)
    .navigation();

 // 指定Flag
 ARouter.getInstance()
    .build("/home/main")
    .withFlags();
    .navigation();

 // 覺得接口不夠多,可以直接拿出Bundle賦值
 ARouter.getInstance()
    .build("/home/main")
    .getExtra();

 // 使用綠色通道(跳過所有的攔截器)
 ARouter.getInstance().build("/home/main").greenChannal().navigation();

Gradle依賴

dependencies {
 apt 'com.alibaba:arouter-compiler:1.0.1'
 compile 'com.alibaba:arouter-api:1.0.2'
}

關于如何搭建Alibaba-ARouter中的Android頁面路由框架就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI