美文网首页
组件化开发-手写路由

组件化开发-手写路由

作者: 有腹肌的豌豆Z | 来源:发表于2020-10-18 12:57 被阅读0次

    该框架仿照Arouter实现的,目的是学习Arouter框架。

    框架的实现主要包括router_core、router_annotation和router_compiler三个部分。

    • annotation-api:核心api,用来实现路由模块的跳转功能;
    • annotation:自定义注解,用来声明需要路由的页面;
    • annotation-compiler:处理注解,在编译时根据自定义注解生成注册路由表的Java类;

    annotation

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

    annotation-compiler

    @AutoService(Processor.class) // 注册注解处理器到虚拟机
    public class Process extends AbstractProcessor {
    
        Filer filer; // 文件操作
    
        @Override
        public synchronized void init(ProcessingEnvironment processingEnv) {
            super.init(processingEnv);
            filer = processingEnv.getFiler();
        }
    
        /**
         * 返回支持的Java版本
         *
         * @return
         */
        @Override
        public SourceVersion getSupportedSourceVersion() {
            return processingEnv.getSourceVersion();
        }
    
        /**
         * 添加 目标注解
         *
         * @return
         */
        @Override
        public Set<String> getSupportedAnnotationTypes() {
            Set<String> types = new HashSet<>();
            types.add(Route.class.getCanonicalName());
            return types;
        }
    
        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            //生成文件代码
            Set<? extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(Route.class);
            Map<String, String> map = new HashMap<>();
            for (Element element : elementsAnnotatedWith) {
                // TypeElement
                // VariableElement
                TypeElement typeElement = (TypeElement) element;
                //com.ysten.fuxi01.MainActivity
                String className = typeElement.getQualifiedName().toString();
                String pathName = typeElement.getAnnotation(Route.class).path();
                map.put(pathName, className + ".class");
            }
            if (map.size() == 0) {
                return false;
            }
    
            //
            Writer writer = null;
            //
            String className = "ActivityUtils" + System.currentTimeMillis();
            try {
                JavaFileObject classFile = filer.createSourceFile("com.shark.router." + className);
                writer = classFile.openWriter();
                writer.write("package com.shark.router;\n" +
                        "\n" +
                        "import com.sharkz.annotation_api.Arouter;\n" +
                        "import com.sharkz.annotation_api.IRouter;\n" +
                        "\n" +
                        "public class " + className + " implements IRouter {\n" +
                        "    @Override\n" +
                        "    public void putActivity() {\n");
    
                Iterator<String> iterator = map.keySet().iterator();
                while (iterator.hasNext()) {
                    String activityKey = iterator.next();
                    String cls = map.get(activityKey);
                    writer.write("        Arouter.getInstance().putActivity(");
                    writer.write("\"" + activityKey + "\"," + cls + ");");
                }
                writer.write("\n}\n" +
                        "}");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (writer != null) {
                    try {
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    
            return false;
        }
    }
    
    
    

    build.gradle

    plugins {
        id 'java-library'
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
    
        // 系统的注解处理器
        implementation 'com.google.auto.service:auto-service:1.0-rc6'
        annotationProcessor 'com.google.auto.service:auto-service:1.0-rc6'
    
        // 目前没有用到 另外一种形式 生成代码的
        // implementation 'com.squareup:javapoet:1.12.1'
    
        // 定义注解的module
        implementation project(path: ':annotation')
    }
    
    java {
        sourceCompatibility = JavaVersion.VERSION_1_7
        targetCompatibility = JavaVersion.VERSION_1_7
    }
    

    annotation-api

    public interface IRouter {
        void putActivity();
    }
    
    public class Arouter {
    
        private static Arouter instance;
        private Context mContext;
        private static Map<String, Class<? extends Activity>> activityMap;
    
        /**
         * 获取到单例
         *
         * @return
         */
        public static Arouter getInstance() {
            if (instance == null) {
                synchronized (Arouter.class) {
                    instance = new Arouter();
                    activityMap = new ArrayMap<>();
                }
    
            }
            return instance;
        }
    
        /**
         * 添加 Activity到 路由表
         *
         * @param activityName 路径名
         * @param cls          com.sharkz.login.LoginActivity.class 全路径class name
         */
        public void putActivity(String activityName, Class cls) {
            if (cls != null && !TextUtils.isEmpty(activityName)) {
                activityMap.put(activityName, cls);
            }
        }
    
        /**
         * 初始化 必须在Application 中初始化
         *
         * @param context app
         */
        public void init(Context context) {
            mContext = context;
            // 这里的 com.shark.router 就是注解处理器里面的 自动生成代码的包名 一定要一样 否则获取不到数据
            List<String> className = getAllActivityUtils("com.shark.router");
            for (String cls : className) {
                try {
                    Class<?> aClass = Class.forName(cls);
                    if (IRouter.class.isAssignableFrom(aClass)) {
                        IRouter iRouter = (IRouter) aClass.newInstance();
                        iRouter.putActivity();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 界面 跳转
         *
         * @param activityName 目标 Activity的路径
         */
        public void jumpActivity(String activityName) {
            jumpActivity(activityName, null);
        }
    
        /**
         * 界面跳转
         *
         * @param activityName 目标Activity的绝对路径
         * @param bundle       传递的参数
         */
        public void jumpActivity(String activityName, Bundle bundle) {
            Intent intent = new Intent();
            Class<? extends Activity> aCls = activityMap.get(activityName);
            if (aCls == null) {
                Log.e("wangjitao", " error -- > can not find activityName " + activityName);
                return;
            }
            if (bundle != null) {
                intent.putExtras(bundle);
            }
            intent.setClass(mContext, aCls);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            // TODO 是不是很熟悉了
            mContext.startActivity(intent);
        }
    
        /**
         * 从 DexFile 里面获取 添加到路由表的数据
         *
         * @param packageName
         * @return
         */
        public List<String> getAllActivityUtils(String packageName) {
            List<String> list = new ArrayList<>();
            String path;
            try {
                path = mContext.getPackageManager().getApplicationInfo(mContext.getPackageName(), 0).sourceDir;
                DexFile dexFile = null;
                dexFile = new DexFile(path);
                Enumeration enumeration = dexFile.entries();
                while (enumeration.hasMoreElements()) {
                    String name = (String) enumeration.nextElement();
                    if (name.contains(packageName)) {
                        list.add(name);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return list;
        }
    
    }
    
    

    Demo

    相关文章

      网友评论

          本文标题:组件化开发-手写路由

          本文链接:https://www.haomeiwen.com/subject/jcyzpktx.html