组件化开发-手写路由
2020-10-18 本文已影响0人
有腹肌的豌豆Z
该框架仿照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;
}
}