<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 健康貓android路由組件解析 2017年中我們項目已經開始全面實行模塊化,新增模塊一律使用新module來進行開發,這樣一來可以通過分解業務來降低應用的復雜性,獨立模塊還可以獨立運行,減少構建規模,提高開發速度。 實際上我們的模塊化執行也比較規范,但依然存在一些和模塊化相悖的細節問題,譬如在一個獨立的業務模塊里面引用了其他**業務模塊**。后來了解到這樣做主要是因為需要調用其他模塊已經存在的接口方法,假如再寫一個,會造成重復實現,也給維護增加了難度。這些都是因為我沒有跟大家說明清楚所導致的,所以我把一些重要的方法和概念寫到這份文檔里,同時帶來一些新的功能來簡化大家使用路由組件。 ## 1. 什么是路由 這里路由特指: 1. 將一串字符串/地址映射到某一頁面; 2. 解析這串字符串/地址,可以得到映射的頁面; 3. 通過這串字符串/地址作為目標進行跳轉,可以進入映射的頁面; 這一系列的解決方案,我們稱之為路由。后來因為路由同樣解決了模塊間的跳轉問題,所以把模塊間的方法調用也歸為路由組件要解決的問題。 ## 2. 為什么需要路由 我們的項目加入路由是因為一個后臺動態配置首頁菜單的需求。當時我們已經在醞釀模塊化的相關,所以當這個需求出現的時候,就毫不猶豫的選擇了這個虛擬地址映射的解決方案。 從技術上來說,就是Android中要打開一個新的頁面,需要一個有目標頁面的`Class`或者完整的包名的意圖`Intent`。我們采用模塊化開發的過程中,當我們要跳轉到另一個業務模塊的頁面時候,我們并沒有對應頁面的`Class`,那么開發工作就基本無法進行下去了。如果采用完整包名或者反射的方式獲取`Class`,雖然開發可以繼續,編譯也能通過,但是運行到這里就會停止。即使你再加上錯誤處理,這個雖然解決了暫時性的問題,但是一個完整的包名抽象的程度太低,無法應用到其他地方,譬如我們無法把這串包名給iOS的應用讓他們跳轉到這個頁面。 所以,在這樣一個需要多端統一跳轉和模塊化的需求下,采用這個已經成熟的方案實際上是水到渠成。于是就有了我們最初的路由組件`Router`,下面我給大家介紹這里面的主要功能和使用方法。 ## 3. 路由組件`Router`的功能 路由主要是兩個功能,一個是解析一串地址進行頁面跳轉,這次會帶來一個新的功能來進行模塊間的方法調用。 其實我們的路由庫里面還有一個第三方的消息總線庫EventBus,這個我就不多說了。 * **頁面跳轉** 上面已經介紹過,通過解析一串字符串地址來得到映射的頁面和參數,從而進行頁面跳轉或者錯誤處理。也因為使用了字符串,所以可以使用路由的場景不再局限于java代碼中,例如: 1. 內置瀏覽器跳轉原生頁面 通過重寫`shouldOverrideUrl`方法,里面判斷要跳轉的地址是否已經映射到原生頁面,從而進行路由選擇。這樣處理可以讓我們在瀏覽H5頁面的時候無縫切換到原生頁面,開發上對混合開發的效率也提高不少。 2. 外部瀏覽器喚起應用并跳轉到對應頁面 通過配置好manifest的相關信息,可以在外部瀏覽器地址輸入應用地址喚起App,喚起頁再通過路由來解析地址來進入指定頁面。這種方式給外部導流帶來了便捷。 3. 應用內跳轉 在應用內,任何需要跳轉的地方都可以使用,無論是消息的頁面跳轉,還是普通的跳轉,后臺配置的動態菜單入口,輪播圖跳轉,只要是正確的地址,不管自身模塊是否有對應的頁面映射,最終集成的應用都可以正確的處理,并且有足夠的靈活性。 * **方法調用** 模塊化開發中,有一類模塊間通信的需求,就是跨模塊調用api,譬如需要調用其他模塊的特定接口。如果自己在本模塊內重新實現一遍,以后接口改動的時候維護起來比較麻煩,所以目前大家采取了直接引用其他業務模塊的方式。這跟模塊化要解決的問題相悖,因為這相當于重新引入了復雜度和規模。當這些需求逐漸增多的時候,你會發現,你的“獨立模塊”實際上就是一整個應用。 為了解決這個問題,健康貓的公共模塊其實有一個解決的類,叫`HMActionHelper`。里面有一系列模塊需要暴露出來的公共接口,并且在主項目初始化的時候注入各模塊的實現。雖然這種方案也是面向接口,但是實現的方式不太優雅,后期的擴展能力也比較弱,而且跟我們的路由組件庫完全獨立,所以新版本(1.0.35以后)在`Router`中增加了此功能,下面會給大家介紹使用方法。 ## 4. 使用方法 頁面跳轉現在可以通過注解來進行快速生成映射和頁面參數映射,后續計劃會把api調用也用注解進行簡化。 ### **頁面跳轉** * (舊)- 首先要建立 地址-頁面 的映射,由于每個app的host都是一樣的,所以映射的地址部分只是path部分,例如: Router.addActivity("/Setting/BlackList", BlacklistManagementActivity.class); 在需要跳轉的地方,使用Router來解析整個地址串: Router.prepare(context, "healthmall://healthmall.cn/Setting/SettingBlack").go(); 如果需要頁面參數,就在地址中按照[我們項目的規則](http://10.0.2.21:8090/pages/viewpage.action?pageId=26869801)添加參數,并且在打開頁面的intent中獲取對應的值: // 地址 String url = "healthmall://healthmall.cn/Setting/SettingBlack?params={\"id\"=1}"; // 頁面中 int id = getIntent().getIntExtra("id"); // 但是在健康貓項目中,由于剛開始時候沒有處理類型的問題,所以如果是取int值,實際上是下面這樣的: int id = (int) Double.pareDouble(getIntent().getStringExtra("id")); // 在太陽神項目中,這個問題被修復了,但是健康貓的為了保持現有的兼容,暫時不去改變。 // 但我們后面介紹注解的方式,則為這兩種情況都做了兼容,所以注解的使用方式不需要區分項目。 * **(新)**- 新的使用方式是通過注解來輕松解決以上重復代碼。 首先需要導包: implementation "com.healthmall.android:router-annotation:$router_version" // 注解包 // 如果不需要kotlin支持 annotationProcessor "com.healthmall.android:router-compiler:$router_version" // 注解處理 // 如果需要kotlin kapt "com.healthmall.android:router-compiler:$router_version" 模塊的gradle配置: defaultConfig{ ... javaCompileOptions { annotationProcessorOptions { arguments = [moduleName: project.getName()] } } } 地址映射部分,使用`RouterPath`注解來標明這是一個路由頁面,注解的value為地址的path部分,例如: @RouterPath("/Setting/SettingBlack") public class BlacklistManagementActivity extends ... { ... } 注解處理器會生成跟上面(舊)一樣的映射代碼,存放在對應一個叫(模塊名+RouterInit)的類的`init`靜態方法里面,例如`module_lifeclub`,會生成一個叫`LifeclubRouterInit`的類,然后在主工程里面調用`init`方法為生活館模塊的路由頁面統一建立映射即可。 頁面參數部分,使用`@RouterParam`注解來注入到一個類變量,注解的value為參數的key,然后在使用這些成員之前,先調用`Router.inject(activity)`來完成參數注入。例如: @RouterPath("/Setting/SettingBlack") public class BlacklistManagementActivity extends ... { // 注意屬性要是public類型 @RouterParam("id") public int id; @Override public void onCreate(Bundle saveInstance) { Router.inject(this); ...id... } } 注解處理器會為擁有`@RouterParam`的路由頁面生成一個`ActivityName_Inject`的類,在開發中我們無須關注,有興趣的可以看一看生成的代碼。 要注意的是在**Kotlin Class**中,因為kotlin使用標準化get set,所以按照Java的方式去寫成員變量,生成的字節碼里面成員變量是私有的,而我們的Inject類是java代碼,沒辦法直接訪問到,所以需要`@JvmField`注解來幫忙生成公開的變量。目前沒找到好的辦法區分源文件是哪種格式,所以暫時先這樣吧: @RouterPath("/Setting/SettingBlack") class BlacklistManagementActivity: Activity { @RouterParam("id") @JvmField var id: Int = 0 @RouterParam("name") lateinit var name: String } 如果參數的類型是`String`,可以選擇使用`lateinit`關鍵字來代替使用`@JvmField`,但是如果你的參數不一定會被初始化的話,不建議使用。因為`lateinit`關鍵字修飾的是非空類型,在給它設置值之前都是不能使用的,空操作符對它也不會生效(因為初始化值之前調用都會報錯)。如果路由定義為可空但你非選擇這樣使用,那么可以在調用它之前,用`::屬性名.isLateinit`來反射得到它是否已經初始化。總之是十分不推薦。 ### 跨模塊方法調用 為什么會有跨模塊方法調用這種需求,上面已經闡述明確,現在直接看一下使用方法。 首先在公共模塊下定義好接口并繼承`com.gzdxjk.ihealth.router.action.Action`,然后使用`Router.find`來找到對應的實現類或者代理。實現者需要實現定義的接口,并且在主項目運行時盡可能早的注入實現類。如果沒有實現類,接口方法調用將不會發生,并且返回值為`null`。 示例: package common; // 公共模塊中定義接口 public interface TestAction extends Action { void test(String id, ApiCallBack<String> callback); } ---- package other; // 其他模塊實現接口 class TestActionImpl1 implements TestAction { @Override public void test(String id, ApiCallBack<String> callback) { ... } } ---- package caller; ... // 目標模塊方法調用 Router.find(TestAction.class).test("9527", new ApiCallBack<String>(){ ... }); ---- // 主模塊注入實現,后續會改成注解,無須再手動注入 Router.add(new TestActionImpl1());
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看