日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

【Android 组件化】路由组件 ( 组件间共享的服务 )

發布時間:2025/6/17 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android 组件化】路由组件 ( 组件间共享的服务 ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、組件間共享的服務
  • 二、注解處理器添加對上述 " 組件間共享的服務 " 的支持
  • 三、注解處理器 生成代碼規則
  • 四、完整注解處理器代碼 及 生成的 Java 代碼
    • 1、注解處理器代碼
    • 2、app 模塊中的注解類生成的 Java 源碼
    • 3、library2 模塊中的注解類生成的 Java 源碼
  • 五、博客資源

組件化系列博客 :

  • 【Android 組件化】從模塊化到組件化
  • 【Android 組件化】使用 Gradle 實現組件化 ( Gradle 變量定義與使用 )
  • 【Android 組件化】使用 Gradle 實現組件化 ( 組件模式與集成模式切換 )
  • 【Android 組件化】使用 Gradle 實現組件化 ( 組件 / 集成模式下的 Library Module 開發 )
  • 【Android 組件化】路由組件 ( 路由組件結構 )
  • 【Android 組件化】路由組件 ( 注解處理器獲取被注解的節點 )
  • 【Android 組件化】路由組件 ( 注解處理器中使用 JavaPoet 生成代碼 )
  • 【Android 組件化】路由組件 ( 注解處理器參數選項設置 )
  • 【Android 組件化】路由組件 ( 構造路由表中的路由信息 )
  • 【Android 組件化】路由組件 ( 使用 JavaPoet 生成路由表類 )




一、組件間共享的服務



路由除了支持 Activity 之外 , 還要支持 組件間共享的服務 如 工具類 , 邏輯功能 等 ;

注意 : 這里的 " 組件間共享的服務 " 不是 444 大組件中的 Service 組件 , 是 任意的 , 實現了 IService 接口的 Java 類 , 可以是工具類 , 業務邏輯 , 等等 ;

定義空的接口 IService , 令 需要共享的服務類 實現接口 , 該接口沒有實際的意義 , 僅用于標記該接口需要納入路由組件管理 , 起標記作用 ;

package kim.hsl.route_core.template;/*** 需要跨組件通信的服務需要實現該接口* 用于標記服務*/ public interface IService { }

接口定義位置 :

跨組件調用時 , 需要暴露出一個接口 , 接口必須實現上述 IService 接口 , 用于作為標識 , 注解處理器中 , 通過判斷該注解節點的類型是不是該接口的子類 , 如果是則生成 路由信息 , 加入到 路由表 中 ;


IService 接口僅用與 標識 服務是否在 組件間共享 ;

針對每個具體的服務 , 還要在 底層依賴庫 中定義一系列的接口 , 這里的底層依賴庫是所有的 Module 組件都要依賴的 Android Library Module 依賴庫 ;

在其中定義一個接口 ComponentService , 繼承 IService 接口 , 在該接口中定義一系列需要暴露的方法 ;

package kim.hsl.base;import kim.hsl.route_core.template.IService;/*** 暴露一個接口*/ public interface ComponentService extends IService {void doSomething(); }

該接口定義位置 : 所有的組件都依賴 base 依賴庫 ;


在具體的組件中 , 實現上述 ComponentService 接口 , 并添加 @Route 注解 ;

package kim.hsl.library2;import android.util.Log;import kim.hsl.base.ComponentService; import kim.hsl.router_annotation.Route;@Route(path = "/library2/StringService") public class StringService implements ComponentService {@Overridepublic void doSomething() {Log.i("StringService", "library2 組件中的 StringService 服務 ");} }

該類定義位置 : 在任意模塊都可以調用該類 ;





二、注解處理器添加對上述 " 組件間共享的服務 " 的支持



之前在注解處理器中 , 只支持 android.app.Activity 的路由節點添加 ;

// 獲取 android.app.Activity 類型的注解節點 TypeElement activityElement = mElementUtils.getTypeElement("android.app.Activity");// 判斷 typeMirror 注解節點是否是 Activity 類型 if (mTypeUtils.isSubtype(element.asType(), activityElement.asType())) {// 該節點是 android.app.Activity 類型的routeBean = new RouteBean(RouteBean.Type.ACTIVITY, // 路由對象類型element, // 路由節點null, // 類對象route.path(), // 路由地址route.group()); // 路由組 }

當前注解處理器中 , 支持 kim.hsl.route_core.template.IService 類型的 路由節點 添加 ;

// 獲取 android.app.Activity 類型的注解節點 TypeElement activityElement = mElementUtils.getTypeElement("android.app.Activity"); // 獲取 組件間共享服務 的接口, 該接口僅用于表示組件類型 TypeElement iServiceElement = mElementUtils.getTypeElement("kim.hsl.route_core.template.IService");// 判斷 typeMirror 注解節點是否是 Activity 類型 if (mTypeUtils.isSubtype(element.asType(), activityElement.asType())) {// 該節點是 android.app.Activity 類型的routeBean = new RouteBean(RouteBean.Type.ACTIVITY, // 路由對象類型element, // 路由節點null, // 類對象route.path(), // 路由地址route.group()); // 路由組 }else if (mTypeUtils.isSubtype(element.asType(), iServiceElement.asType())) {// 該節點是 kim.hsl.route_core.template.IService 類型的routeBean = new RouteBean(RouteBean.Type.ISERVICE, // 路由對象類型element, // 路由節點null, // 類對象route.path(), // 路由地址route.group()); // 路由組 }else{// 該節點不是 android.app.Activity 類型的throw new RuntimeException("@Route 注解節點類型錯誤"); }



三、注解處理器 生成代碼規則



注解處理器的 process 方法調用 , 是按照 Module 模塊進行的 ;

如果 Module 模塊中有相關注解 , 傳入的 Set<? extends TypeElement> set 參數不為空 , 就會進行相關處理 ;

如果 Module 模塊中沒有相關注解 , 傳入的 Set<? extends TypeElement> set 參數為空 , 此時就不進行后續操作 ;


下圖紅色的 library1 模塊中沒有注解 ;

藍色的 library2 模塊中添加了 @Route(path = “/library2/StringService”) 注解 ;

綠色的 app 模塊中添加了 @Route(path = “/app/MainActivity”) 注解 ;

Module 模塊中 , 使用注解生成的源碼 , 都在對應模塊的 " build\generated\ap_generated_sources\debug\out\ " 目錄中 ;





四、完整注解處理器代碼 及 生成的 Java 代碼





1、注解處理器代碼


package kim.hsl.router_compiler;import com.google.auto.service.AutoService; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeSpec;import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap;import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.Processor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedOptions; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.tools.Diagnostic;import kim.hsl.router_annotation.Route; import kim.hsl.router_annotation.model.RouteBean;import static javax.lang.model.element.Modifier.PUBLIC;// 注解處理器接收的參數 @SupportedOptions("moduleName") // 自動注冊注解處理器 @AutoService(Processor.class) // 支持的注解類型 @SupportedAnnotationTypes({"kim.hsl.router_annotation.Route"}) // 支持的 Java 版本 @SupportedSourceVersion(SourceVersion.RELEASE_8) public class RouterProcessor extends AbstractProcessor {/*** 注解處理器中使用 Messager 對象打印日志*/private Messager mMessager;/*** 用于寫出生成的 Java 代碼*/private Filer mFiler;/*** 注解節點工具*/private Elements mElementUtils;/*** 類工具*/private Types mTypeUtils;/*** 獲取的 moduleName 參數*/private String mModuleName;/*** 管理路由信息* 鍵 ( Key ) : 路由分組名稱* 值 ( Value ) : 路由信息集合*/private HashMap<String, ArrayList<RouteBean>> mGroupMap = new HashMap<>();/*** 管理 路由表信息* 鍵 ( Key ) : 組名* 值 ( Value ) : 類名*/private Map<String, String> mRootMap = new TreeMap<>();/*** 該函數在初始化時調用 , 相當于構造函數* @param processingEnvironment*/@Overridepublic synchronized void init(ProcessingEnvironment processingEnvironment) {super.init(processingEnvironment);// 獲取打印日志接口this.mMessager = processingEnvironment.getMessager();// 測試日志打印mMessager.printMessage(Diagnostic.Kind.NOTE, "Messager Print Log");this.mFiler = processingEnvironment.getFiler();this.mElementUtils = processingEnvironment.getElementUtils();this.mTypeUtils = processingEnvironment.getTypeUtils();// 獲取 moduleName 參數// 先獲取 注解處理器 選項Map<String, String> options = processingEnvironment.getOptions();if (options != null){mModuleName = options.get("moduleName");mMessager.printMessage(Diagnostic.Kind.NOTE, "打印 moduleName 參數 : " + mModuleName);}}/*** 該函數在注解處理器注冊時自動執行, 是處理注解的核心函數** Set<? extends TypeElement> set 參數 : 該集合表示使用了相關注解的節點的集合** @param set* @param roundEnvironment* @return*/@Overridepublic boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {if (set == null || set.isEmpty()){// 如果沒有檢測到注解 , 直接退出return false;}// 獲取被 @Route 注解的節點// 這些 注解節點 都是類節點 , TypeElement 類型的Set<? extends Element> routeElements = roundEnvironment.getElementsAnnotatedWith(Route.class);generateRouteClass(routeElements);// 生成 路由組件 分組表 對應的 Java 類generateGroupTable();// 生成 路由組件 路由表 對應的 Java 類return true;}/*** 生成 路由組件 分組表 對應的 Java 類*/private void generateGroupTable() {// 獲取要生成的類 需要實現的接口節點TypeElement iRouteGroup = mElementUtils.getTypeElement("kim.hsl.route_core.template.IRouteGroup");// 打印類節點全類名mMessager.printMessage(Diagnostic.Kind.NOTE,"打印 路由表 需要實現的接口節點 iRouteGroup : " + iRouteGroup.getQualifiedName());// 生成參數類型 Map<String, RouteBean> atlasParameterizedTypeName atlasType = ParameterizedTypeName.get(ClassName.get(Map.class),ClassName.get(String.class),ClassName.get(RouteBean.class));// 生成參數 Map<String, RouteBean> atlasParameterSpec atlasValue = ParameterSpec.builder(atlasType, "atlas").build();// 遍歷 HashMap<String, ArrayList<RouteBean>> mGroupMap = new HashMap<>() 路由分組// 為每個 路由分組 創建一個類for (Map.Entry<String, ArrayList<RouteBean>> entry : mGroupMap.entrySet()){// 創建函數 loadIntoMethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("loadInto").addModifiers(Modifier.PUBLIC).addAnnotation(Override.class).addParameter(atlasValue);// 函數體中的代碼生成// 獲取 ArrayList<RouteBean> 數據ArrayList<RouteBean> groupRoutes = entry.getValue();// 組名String groupName = "";// 生成函數體代碼for (RouteBean routeBean : groupRoutes){// 獲取組名groupName = routeBean.getRouteGroup();// $S 表示字符串// $T 表示類// $L 表示字面量 , 原封不動的字符串替換methodBuilder.addStatement("atlas.put($S, new $T($T.$L, $T.class, $S, $S))",// $S 字符串 : "main"routeBean.getRouteGroup(),// $T 類名 : RouteBeanClassName.get(RouteBean.class),// $T 類名 : TypeClassName.get(RouteBean.Type.class),// $L 字面量 : ACTIVITYrouteBean.getType(),// $T 類名 : kim.hsl.component.MainActivity 類ClassName.get((TypeElement) routeBean.getElement()),// $S 字符串 : "/app/MainActivity"routeBean.getRouteAddress(),// $S 字符串 : "app"routeBean.getRouteGroup());}// 創建類// 構造類名 Router_Group_mainString groupClassName = "Router_Group_" + groupName;// 創建類TypeSpec typeSpec = TypeSpec.classBuilder(groupClassName).addSuperinterface(ClassName.get(iRouteGroup)).addModifiers(PUBLIC).addMethod(methodBuilder.build()).build();// 生成 Java 源碼文件JavaFile javaFile = JavaFile.builder("kim.hsl.router", typeSpec).build();// 將 Java 源文件寫出到相應目錄中try {mMessager.printMessage(Diagnostic.Kind.NOTE,"輸出文件 : " + groupClassName);javaFile.writeTo(mFiler);} catch (IOException e) {e.printStackTrace();mMessager.printMessage(Diagnostic.Kind.NOTE,"輸出文件出現異常");}finally {mMessager.printMessage(Diagnostic.Kind.NOTE,"輸出文件完畢");}// 統計路由表信息mRootMap.put(groupName, groupClassName);}}private void generateRouteClass(Set<? extends Element> routeElements) {// 獲取 android.app.Activity 類型的注解節點TypeElement activityElement = mElementUtils.getTypeElement("android.app.Activity");// 獲取 組件間共享服務 的接口, 該接口僅用于表示組件類型TypeElement iServiceElement = mElementUtils.getTypeElement("kim.hsl.route_core.template.IService");// 處理 @Route(path = "app/MainActivity") 節點for (Element element : routeElements) {// 獲取 Route 注解Route route = element.getAnnotation(Route.class);// 路由表中的單個路由對象RouteBean routeBean = null;// 判斷 typeMirror 注解節點是否是 Activity 類型if (mTypeUtils.isSubtype(element.asType(), activityElement.asType())) {// 該節點是 android.app.Activity 類型的routeBean = new RouteBean(RouteBean.Type.ACTIVITY, // 路由對象類型element, // 路由節點null, // 類對象route.path(), // 路由地址route.group()); // 路由組}else if (mTypeUtils.isSubtype(element.asType(), iServiceElement.asType())) {// 該節點是 kim.hsl.route_core.template.IService 類型的routeBean = new RouteBean(RouteBean.Type.ISERVICE, // 路由對象類型element, // 路由節點null, // 類對象route.path(), // 路由地址route.group()); // 路由組}else{// 該節點不是 android.app.Activity 類型的throw new RuntimeException("@Route 注解節點類型錯誤");}// 檢查路由地址checkRouteAddress(routeBean);// 打印路由信息mMessager.printMessage(Diagnostic.Kind.NOTE,"打印路由信息 : " + routeBean.toString());// 處理路由信息分組routeGroup(routeBean);}}/*** 處理路由信息分組* @param routeBean*/private void routeGroup(RouteBean routeBean) {// 首先從 groupMap 集合中獲取該分組的所有 路由信息ArrayList<RouteBean> routeBeans = mGroupMap.get(routeBean.getRouteGroup());if (routeBeans == null){// 如果從 mGroupMap 獲取的該分組的路由信息集合為空// 則創建新集合, 放置路由信息, 并加入到 mGroupMap 中routeBeans = new ArrayList<>();routeBeans.add(routeBean);mGroupMap.put(routeBean.getRouteGroup(), routeBeans);}else{// 從 mGroupMap 獲取的路由分組對應的路由信息集合不為空// 直接添加 路由信息 即可routeBeans.add(routeBean);}}/*** 驗證路由地址* @Route(path = "/app/MainActivity")* @param routeBean*/private void checkRouteAddress(RouteBean routeBean){// 獲取路由地址String routeAddress = routeBean.getRouteAddress();// 獲取路由分組String routeGroup = routeBean.getRouteGroup();// 驗證路由地址是否以 "/" 開頭if (!routeAddress.startsWith("/")) {throw new RuntimeException("路由地址 " + routeAddress + " 格式錯誤");}// 如果路由地址的分組為空 ,// 則截取第 0 和 第 1 個 "/" 之間的字符串作為分組名稱if (routeGroup == null || "".equals(routeGroup)){String group = routeAddress.substring(routeAddress.indexOf("/", 0) + 1,routeAddress.indexOf("/", 1));if (group == null || "".equals(group)){throw new RuntimeException("路由地址 " + routeAddress + " 獲取分組錯誤");}// 打印組名mMessager.printMessage(Diagnostic.Kind.NOTE,"打印路由地址 " + routeAddress + " 的組名為 " + group);// 正式設置路由地址分組routeBean.setRouteGroup(group);}} }

2、app 模塊中的注解類生成的 Java 源碼


Module 模塊中 , 使用注解生成的源碼 , 都在對應模塊的 " build\generated\ap_generated_sources\debug\out\ " 目錄中 ;

app 中的注解類 :

@Route(path = "/app/MainActivity") public class MainActivity extends Activity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);} }

生成的源碼 : 生成源碼路徑 D:\002_Project\002_Android_Learn\Component\app\build\generated\ap_generated_sources\debug\out\kim\hsl\router\Router_Group_app.java ;

package kim.hsl.router;import java.lang.Override; import java.lang.String; import java.util.Map; import kim.hsl.component.MainActivity; import kim.hsl.route_core.template.IRouteGroup; import kim.hsl.router_annotation.model.RouteBean;public class Router_Group_app implements IRouteGroup {@Overridepublic void loadInto(Map<String, RouteBean> atlas) {atlas.put("app", new RouteBean(RouteBean.Type.ACTIVITY, MainActivity.class, "/app/MainActivity", "app"));} }

3、library2 模塊中的注解類生成的 Java 源碼


Module 模塊中 , 使用注解生成的源碼 , 都在對應模塊的 " build\generated\ap_generated_sources\debug\out\ " 目錄中 ;

library2 中的注解類 :

package kim.hsl.library2;import android.util.Log;import kim.hsl.base.ComponentService; import kim.hsl.router_annotation.Route;@Route(path = "/library2/StringService") public class StringService implements ComponentService {@Overridepublic void doSomething() {Log.i("StringService", "library2 組件中的 StringService 服務 ");} }

生成的源碼 : 生成源碼路徑 D:\002_Project\002_Android_Learn\Component\library2\build\generated\ap_generated_sources\debug\out\kim\hsl\router\Router_Group_library2.java ;

package kim.hsl.router;import java.lang.Override; import java.lang.String; import java.util.Map; import kim.hsl.library2.StringService; import kim.hsl.route_core.template.IRouteGroup; import kim.hsl.router_annotation.model.RouteBean;public class Router_Group_library2 implements IRouteGroup {@Overridepublic void loadInto(Map<String, RouteBean> atlas) {atlas.put("library2", new RouteBean(RouteBean.Type.ISERVICE, StringService.class, "/library2/StringService", "library2"));} }



五、博客資源



博客源碼 :

  • GitHub : https://github.com/han1202012/Component
  • CSDN 下載 :


《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的【Android 组件化】路由组件 ( 组件间共享的服务 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。