簡單好用的Android頁面路由框架

前言

 码报开奖结果本期 www.iwqgw.icu         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開發中,最常見也是最常用的功能就是頁面的跳轉,我們經常需要面對從瀏覽器或者其他App跳轉到自己App中頁面的需求,不過就算是簡簡單單的頁面跳轉,隨著時間的推移,也會遇到一些問題:

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

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

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

  4. 跨??槲薹ㄏ允揭覽擔涸贏pp小有規模的時候,我們會對App做水平拆分,按照業務拆分成多個子???,之間完全解耦,通過打包流程控制App功能,這樣方便應對大團隊多人協作,互相邏輯不干擾,這時候只能依賴隱式Intent跳轉,書寫麻煩,成功與否難以控制。

另一個輪子

為了解決以上問題,我們需要一款能夠解耦、簡單、功能多、定制性較強、支持攔截邏輯的路由組件:我們選擇了Alibaba的ARouter,偷個懶,直接貼ARouter的中文介紹文檔:


Demo gif

一、功能介紹

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

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

  3. 支持多??楣こ討惺褂?,允許分別打包,包結構符合Android包規范即可(*)

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

  5. 支持服務托管,通過ByName,ByType兩種方式獲取服務實例,方便面向接口開發與跨??櫚饔媒怦?*)

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

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

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

  9. 豐富的API和可定制性

  10. 被ARouter管理的頁面、攔截器、服務均無需主動注冊到ARouter,被動發現

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

二、不支持的功能

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

  2. 不能動態加載代碼??楹吞砑勇酚曬嬖?考慮支持)

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

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

三、典型應用場景

  1. 從外部URL映射到內部頁面,以及參數傳遞與解析

  2. 跨??橐趁嫣?,??榧浣怦?/p>

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

  4. 跨??锳PI調用,??榧浣怦?注冊ARouter服務的形式,通過接口互相調用)

四、基礎功能

  1. 添加依賴和配置

    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'
         ...
     }
  2. 添加注解

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

     ARouter.init(mApplication); // 盡可能早,推薦在Application中初始化
  4. 發起路由操作

     // 1. 應用內簡單的跳轉(通過URL跳轉在'中階使用'中)
     ARouter.getInstance().build("/test/1").navigation(); // 2. 跳轉并攜帶參數
     ARouter.getInstance().build("/test/1")             .withLong("key1", 666L)             .withString("key3", "888")             .navigation();
  5. 添加混淆規則(如果使用了Proguard)

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

五、進階用法

  1. 通過URL跳轉

     // 新建一個Activity用于監聽Schame事件
     // 監聽到Schame事件之后直接傳遞給ARouter即可
     // 也可以做一些自定義玩法,比方說改改URL之類的
     // //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>
  2. 使用ARouter協助解析參數類型

     // URL中的參數會默認以String的形式保存在Bundle中
     // 如果希望ARouter協助解析參數(按照不同類型保存進Bundle中)
     // 只需要在需要解析的參數上添加 @Param 注解
     @Route(path = "/test/1")
     public class Test1Activity extends Activity {     @Param                   // 聲明之后,ARouter會從URL中解析對應名字的參數,并按照類型存入Bundle
         public String name;     @Param
         private int age;     @Param(name = "girl")   // 可以通過name來映射URL中的不同參數
         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
         }
     }
  3. 開啟ARouter參數自動注入(實驗性功能,不建議使用,正在開發?;げ唄?

     // 首先在Application中重寫 attachBaseContext方法,并加入ARouter.attachBaseContext();
     @Override
     protected void attachBaseContext(Context base) {    super.attachBaseContext(base);
    
        ARouter.attachBaseContext();
     } // 設置ARouter的時候,開啟自動注入
     ARouter.enableAutoInject(); // 至此,Activity中的屬性,將會由ARouter自動注入,無需 getIntent().getStringExtra("xxx")等等
  4. 聲明攔截器(攔截跳轉過程,面向切面搞事情)

     // 比較經典的應用就是在跳轉過程中處理登陸事件,這樣就不需要在目標頁重復做登陸檢查
    
     // 攔截器會在跳轉之間執行,多個攔截器會按優先級順序依次執行
     @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("我覺得有點異常"));      // 覺得有問題,中斷路由流程
    
             // 以上兩種至少需要調用其中一種,否則會超時跳過
         }     /**
          * 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) {
    
         }
     }
  5. 處理跳轉結果

     // 通過兩個參數的navigation方法,可以獲取單次跳轉的結果
     ARouter.getInstance().build("/test/1").navigation(this, new NavigationCallback() {     @Override
         public void onFound(Postcard postcard) {
               ...
         }     @Override
         public void onLost(Postcard postcard) {
             ...
         }
     });
  6. 自定義全局降級策略

         // 實現DegradeService接口,并加上一個Path內容任意的注解即可
        @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) {
    
           }
         }
  7. 為目標頁面聲明更多信息

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

     /**
      * 聲明接口
      */
     public interface IService extends IProvider {     String hello(String name);
     } /**
      * 實現接口
      */
     @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) {
    
         }
     }
  9. 使用ARouter管理服務(二) 發現服務

     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這種方式寫起來比較方便,但如果存在多實現的情況時,SDK不保證能獲取到你想要的實現
  10. 使用ARouter管理服務(三) 管理依賴

        可以通過ARouter service包裝您的業務邏輯或者sdk,在service的init方法中初始化您的sdk,不同的sdk使用ARouter的service進行調用,
    每一個service在第一次使用的時候會被初始化,即調用init方法。
        這樣就可以告別各種亂七八糟的依賴關系的梳理,只要能調用到這個service,那么這個service中所包含的sdk等就已經被初始化過了,完全不需要
    關心各個sdk的初始化順序。

六、更多功能

  1. 初始化中的其他設置

     ARouter.openLog();    // 開啟日志
     ARouter.printStackTrace(); // 打印日志的時候打印線程堆棧
  2. 詳細的API說明

     // 構建標準的路由請求
     ARouter.getInstance().build("/home/main").navigation(); // 構建標準的路由請求,并指定分組
     ARouter.getInstance().build("/home/main", "ap").navigation(); // 構建標準的路由請求,通過Uri直接解析
     Uri uri; ARouter.getInstance().build(uri).navigation(); // 構建標準的路由請求,startActivityForResult
     // navigation的第一個參數必須是Activity,第二個參數則是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();

附錄

ARouter Github鏈接
Demo apk

  • 最新版本
    arouter-annotation : 1.0.0
    arouter-compiler : 1.0.1
    arouter-api : 1.0.2

  • Gradle依賴

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

來源:簡書

上一篇: Swift是Android的未來么?

下一篇: Android和H5交互-基礎篇

分享到: 更多
快速时时开奖记录 腾讯欢乐麻将手机版 彩票智能选号软件 最新欢乐生肖娱乐 澳客竞彩 山东时时11选5走势 冷号的规律 捕鱼达人hd下载 竞彩500 马会独家资料提供 重庆时时彩稳赚技巧 双色球开奖视频 11选5免费预测计划软件破解版 三公网站 重庆时时彩高手论坛 北京时时是官方的吗