仿照ARouter思路简单的实现路由

一、 页面跳转

两个页面之间的跳转

    Intent intent = new Intent();
    intent.setClass(A.this, B.class);
    startActivity(intent);

如果直接这样写,B文件删除了,会导致一系列报红,然后项目无法编译。

二、 使用配置文件

    Map<String, Class<?>> clazzMap = new HashMap<>();
    clazzMap.put("/a", A.class);
    clazzMap.put("/b", B.class);
    Intent intent = new Intent();
    Class<?> bClass = clazzMap.get("/b");
    if(bClass != null) {
        intent.setClass(A.this, bClass);
        startActivity(intent);
    }

维护一个classMap,跳转的时候从这个Map里面去找对应的页面,如果没有找到,可以做一些其他操作,比如提示,总体上影响不会太大,最差也就是无响应。

但是有个麻烦的地方在于,需要人工维护这个Map表,一旦文件删除了,但是这个表没有更新,还是会报错闪退。

三、 apt技术

什么是apt技术呢?Annotation processor Tool 注解处理工具。参照ARouter技术,简单的实现一个自动生成路由表的工作。

3.1 首先定义一个注解路由

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.CLASS)
    public @interface Route {
    
        String path();
    }

首先TYPE代表它作用在类上,CLASS代表编译时期仍然存在,可以指定一个path参数,也就是路由表的key。

3.2 定义路由bean

    public class RouteMeta {
    
        /**
         * 注解使用的类对象
         */
        private Class<?> destination;
    
        /**
         * 路由地址
         */
        private String path;
    
        public RouteMeta(Class<?> destination, String path) {
            this.destination = destination;
            this.path = path;
        }
    
        public Class<?> getDestination() {
            return destination;
        }
    
        public void setDestination(Class<?> destination) {
            this.destination = destination;
        }
    
        public String getPath() {
            return path;
        }
    
        public void setPath(String path) {
            this.path = path;
        }
    
    }

保存每一个路由的信息,简单的路由只需要path和class。

既然定义了注解就需要解释它。

3.3 注解解释器

    @AutoService(Processor.class) //谷歌提供的服务,编译时期会自动回调这个类的各个方法
    public class RouteProcessor extends AbstractProcessor {
    
        @Override
        public Set<String> getSupportedAnnotationTypes() {
            Set<String> types = new LinkedHashSet<>();
            types.add(Route.class.getCanonicalName()); //指定支持的注解类型
            return types;
        }
    
        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
            //查找到所有被Route注解的class
            Set<? extends Element> routes = roundEnvironment.getElementsAnnotatedWith(Route.class);
            //自动生成文件
            processRoute(routes);
            return false;
        }
    
        private void processRoute(Set<? extends Element> routes) {
            try {
                //指定生成文件的包名
                String packageName = "com.rjp.fastframework";
                String activityFileName = packageName + ".IProject";
                final String CLASS_SUFFIX = "$Router";
                Filer filer = processingEnv.getFiler();
                //指定生成的文件名
                JavaFileObject javaFileObject = filer.createSourceFile(activityFileName + CLASS_SUFFIX);
                //定义writer,开始构建java文件
                Writer writer = javaFileObject.openWriter();
                //构建的类名
                String clazzName = "IProject" + CLASS_SUFFIX;
    
                writer.write("package " + packageName + ";\n");
                writer.write("import com.rjp.expandframework.route.bean.RouteMeta;\n");
                writer.write("import com.rjp.expandframework.route.interfaces.IRoute;\n");
                writer.write("import java.util.Map;\n");
                writer.write("public class " + clazzName + " implements IRoute {\n");
                writer.write("@Override\n");
                writer.write("public void loadRoute(Map<String, RouteMeta> routes) {\n");
    
                for (Element element : routes) {
                    String pageClass = element.asType().toString();
                    Route route = element.getAnnotation(Route.class);
                    writer.write("routes.put(\"" + route.path() + "\", new RouteMeta(" + pageClass + ".class, \"" + route.path() + "\"));\n");
                }
    
                writer.write("}\n");
                writer.write("}\n");
    
                writer.close();
            }catch (Exception e){
    
            }
        }
    }

3.4 使用注解

    @Route(path = "/main/permission")
    public class PermissionActivity extends Activity {}

3.5 自动生成路由文件

点击build,打开/app/build/generated/source/apt/{channel}/debug/,你就能看到自动生成的文件,里面已经自动化实现了以上writer编写的类代码。

auto-route.png

四、 总结

route.png

参考文章

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。