组件化开发-手写路由

2020-10-18  本文已影响0人  有腹肌的豌豆Z

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

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

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

上一篇下一篇

猜你喜欢

热点阅读