组件化
- 组件化:组件化,去除模块间的耦合,使得每个业务模块可以独立当做App存在,对于其他模块没有直接的依赖关系
- 模块化:模块化就是拆分成多个模块放在不同的Module里面,每个功能的代码都在自己所属的 module 中添加
- 单工程方案,组件以module形式存在,动态配置组件的工程类型;
- 动态修改gradle文件,集成时变为Library插件,独立调试时变为Application插件
- 动态配置ApplicationId 和 AndroidManifest
- 多工程方案,业务组件以library module形式存在于独立的工程,且只有这一个library module。
- 业务组件以library module形式存在于独立的工程
- 发布到Maven仓库,通过引入第三方依赖方式使用
使用路由
- 服务暴露组件
通过AppLifeCycle回调
- 不使用注解器
- 手动把每个界面和相应的Activity对应起来。这个处理过程可以在Application里面做的
routers.put("router://activity/main", MainActivity.class); routers.put("router://activity/main2", Main2Activity.class); routers.put("router://activity/main3", Main3Activity.class); //通过scheme实现跳转 Class aClass = mTables.get(path); Intent intent = new Intent(context, aClass); if (!(context instanceof Activity)) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } context.startActivity(intent);
- 使用注解器
- 自动生成用于注册activity的map代码
- 2.1、 继承AbstractProcessor 每一个处理器都继承与AbstractProcessor,这些方法java虚拟机会自动调用
public class MyProcessor extends AbstractProcessor { @Override public synchronized void init(ProcessingEnvironment env){ } @Override public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { //处理函数,我们需要在这个函数里面写处理特定注解的代码,并生成相应的java文件,RoundEnvironment,通过这个参数我们可以拿到带有特定注解的元素(类,字段,方法啦) } @Override public Set<String> getSupportedAnnotationTypes() { //指定当前的注解处理器处理哪些注解,从返回值可以看到是返回Set的,那就是一个注解处理器可以处理多个注解的 } @Override public SourceVersion getSupportedSourceVersion() { //指定你使用的java版本,通常这里直接返回SourceVersion.latestSupported() } }
- 2.2、注册处理器 需要有特定的文件在src/main/resources/META-INF/services中,文件名是javax.annotation.processing.Processor,内容是处理器的路径
- 2.3、处理器的编写
- 注解存放库
只存放注解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.CLASS) public @interface Route { String value(); }
- 注解解析库
处理注解,并不会增加apk的大小
public class RouterProcessor extends AbstractProcessor { @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); UtilManager.getMgr().init(processingEnv); //ProcessingEnvironment中的内容 //package com.example; // PackageElement //public class Foo { // TypeElement // private int a; // VariableElement // private Foo other; // VariableElement // public Foo () {} // ExecuteableElement // public void setA ( // ExecuteableElement // int newA // TypeElement // ) {} //} } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { UtilManager.getMgr().getMessager().printMessage(Diagnostic.Kind.NOTE, "process"); //获取所有被Route注解的Element Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Route.class); List<TargetInfo> targetInfos = new ArrayList<>(); for (Element element : elements) { // 检查类型 if (!Utils.checkTypeValid(element)) continue; //获取一个被Route注解的类,并添加到list中 TypeElement typeElement = (TypeElement) element; Route route = typeElement.getAnnotation(Route.class); targetInfos.add(new TargetInfo(typeElement, route.value())); } if (!targetInfos.isEmpty()) { generateCode(targetInfos); } return false; } /** * 生成对应的java文件 * * @param targetInfos 代表router和activity */ private void generateCode(List<TargetInfo> targetInfos) { // Map<String, Class<? extends Activity>> routers TypeElement activityType = UtilManager .getMgr() .getElementUtils() .getTypeElement("android.app.Activity"); ParameterizedTypeName actParam = ParameterizedTypeName.get(ClassName.get(Class.class), WildcardTypeName.subtypeOf(ClassName.get(activityType))); ParameterizedTypeName parma = ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), actParam); ParameterSpec parameterSpec = ParameterSpec.builder(parma, "routers").build(); MethodSpec.Builder methodSpecBuilder = MethodSpec.methodBuilder(Constants.ROUTE_METHOD_NAME) .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC) .addParameter(parameterSpec); for (TargetInfo info : targetInfos) { methodSpecBuilder.addStatement("routers.put($S, $T.class)", info.getRoute(), info.getTypeElement()); } TypeElement interfaceType = UtilManager .getMgr() .getElementUtils() .getTypeElement(Constants.ROUTE_INTERFACE_NAME); TypeSpec typeSpec = TypeSpec.classBuilder(Constants.ROUTE_CLASS_NAME) .addSuperinterface(ClassName.get(interfaceType)) .addModifiers(Modifier.PUBLIC) .addMethod(methodSpecBuilder.build()) .addJavadoc("Generated by Router. Do not edit it!\n") .build(); try { JavaFile.builder(Constants.ROUTE_CLASS_PACKAGE, typeSpec) .build() .writeTo(UtilManager.getMgr().getFiler()); } catch (Exception e) { e.printStackTrace(); } } /** * 定义你的注解处理器注册到哪些注解上 */ @Override public Set<String> getSupportedAnnotationTypes() { Set<String> annotations = new LinkedHashSet<>(); annotations.add(Route.class.getCanonicalName()); return annotations; } /** * java版本 */ @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); } }
- 对外API库
public interface IRoute { void initRouter(Map<String, Class<? extends Activity>> routers); } public void init() { try { //获取通过注解生成的文件,执行map的初始化 String className = "com.ai.router.impl.AppRouter"; Class<?> moduleRouteTable = Class.forName(className); Constructor constructor = moduleRouteTable.getConstructor(); IRoute instance = (IRoute) constructor.newInstance(); instance.initRouter(mTables); } catch (Exception e) { e.printStackTrace(); } } //实行跳转 public void openResult(Context context, String path) { if (!TextUtils.isEmpty(mSchemeprefix)) { // router://activity/main path = mSchemeprefix + "://" + path; } try { Class aClass = mTables.get(path); Intent intent = new Intent(context, aClass); if (!(context instanceof Activity)) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } context.startActivity(intent); } catch (Exception e) { e.printStackTrace(); } }
- 注解存放库
只存放注解
- 自动生成用于注册activity的map代码