import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import static com.hxg.hrouter_complier.utils.Consts.KEY_MODULE_NAME;
public abstract class BaseProcessor extends AbstractProcessor {
//生成文件的对象
protected Filer filer;
protected Elements elementUtils;
protected Types types;
protected String moduleName;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
filer = processingEnvironment.getFiler();
types = processingEnv.getTypeUtils();
elementUtils = processingEnvironment.getElementUtils();
Map<String, String> options = processingEnv.getOptions();
if (options != null) {
moduleName = options.get(KEY_MODULE_NAME);
}
}
/**
-
声明这个注解处理器要识别处理的注解
-
@return
*/
@Override
public Set getSupportedAnnotationTypes() {
Set annotations = new HashSet<>();
annotations.add(Route.class.getCanonicalName());
return annotations;
}
/**
-
支持java的源版本
-
@return
*/
@Override
public SourceVersion getSupportedSourceVersion() {
return processingEnv.getSourceVersion();
}
//判断当前是不是activity类
protected boolean isActivity(TypeElement typeElement) {
TypeMirror activityTm = elementUtils.getTypeElement(Consts.ACTIVITY).asType();
if (types.isSubtype(typeElement.asType(), activityTm)) return true;
return false;
}
//判断当前类是fragment
protected boolean isFragment(TypeElement typeElement) {
TypeMirror fragmentTm = elementUtils.getTypeElement(Consts.FRAGMENT).asType();
TypeMirror fragmentTmV4 = elementUtils.getTypeElement(Consts.FRAGMENT_V4).asType();
if (types.isSubtype(typeElement.asType(), fragmentTm)
|| types.isSubtype(typeElement.asType(), fragmentTmV4)) {
return true;
}
return false;
}
}
package com.hxg.hrouter_complier.entity;
public class ClazzType {
public static final String ACTIVITY = “activity”;
public static final String FRAGMENT = “fragment”;
}
package com.hxg.hrouter_complier.entity;
public class ElementType {
private String clazz;
private String type;
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return “ElementType{” +
“, clazz='” + clazz + ‘’’ +
“, type=” + type +
‘}’;
}
}
package com.hxg.hrouter_complier.utils;
public class Consts {
public static final String ACTIVITY = “android.app.Activity”;
public static final String FRAGMENT = “android.app.Fragment”;
public static final String FRAGMENT_V4 = “android.support.v4.app.Fragment”;
public static final String KEY_MODULE_NAME = “AROUTER_MODULE_NAME”;
}
package com.hxg.hrouter_complier.utils;
import java.io.IOException;
import java.io.Writer;
import javax.annotation.processing.Filer;
public class LogUtil {
Writer writer;
String utilName;
public LogUtil(Filer filer, String moduleName) {
utilName = “HRouter L o g U t i l LogUtil LogUtil” + moduleName;
try {
writer = filer.createSourceFile(“com.hxg.android.hrouter.log.” + utilName).openWriter();
writer.write(“package com.hxg.android.hrouter.log;\n” +
“\n” +
“import android.util.Log;\n” +
“import com.hxg.lib_hrouter.ILog;\n” +
“\n” +
“public class " + utilName + " implements ILog {\n” +
“@Override\n” +
“public void logPrint() {\n”);
} catch (IOException e) {
e.printStackTrace();
}
}
public void writerLog(String logString) {
try {
writer.write(" Log.i(“HRouter” + “”,“” + logString + “”);\n");
} catch (IOException e) {
e.printStackTrace();
}
}
public void finallyLog() {
if (writer != null) {
try {
writer.write(“}\n}”);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
到这里我们编译生成的类基本完成,不出意外,编译或运行一下我们项目会生成对应的代码(有个IRouter接口后面会提到)
package com.hxg.android.hrouter.routes;
import com.hxg.lib_hrouter.HRouter;
import com.hxg.lib_hrouter.IRouter;
public class HRouter P r o c e s s o r Processor Processormodule_member implements IRouter {
@Override
public void putClazz() {
HRouter.getInstance().addClazz(“member/blankfragment”,“fragment”,com.hxg.module_member.BlankFragment.class);
HRouter.getInstance().addClazz(“member/member”,“activity”,com.hxg.module_member.MemberActivity.class);
}
}
- 执行生成的类
如何调用呢?因为上面生成的类的包名是我们自己所起,因此我们可以根据通过包名获取这个包下面的所有类名
/**
-
通过包名获取这个包下面的所有类名
-
@param packageName
-
@return
*/
private List getClassName(String packageName) {
//创建一个class对象集合
List classList = new ArrayList<>();
String path = null;
try {
//通过包管理器 获取到应用信息类然后获取到APK的完整路径
path = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0).sourceDir;
//根据APK的完整路径获取到编译后的dex文件目录
DexFile dexfile = new DexFile(path);
//获得编译后的dex文件中的所有class
Enumeration entries = dexfile.entries();
//然后进行遍历
while (entries.hasMoreElements()) {
//通过遍历所有的class的包名
String name = entries.nextElement();
//判断类的包名是否符合我们起的包名(com.hxg.util)
if (name.contains(packageName)) {
//如果符合,就添加到集合中
classList.add(name);
}
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return classList;
}
这样就可以拿到包下所有的类了,然后判断判断这个类是不是实现了IRouter接口找到生成的类,再通过接口的引用调用其生成的方法
//根据包名获取到这个包下面所有的类名
List classList = getClassName(“com.hxg.android.hrouter.routes”);
//遍历
for (String s : classList) {
try {
Class<?> aClass = Class.forName(s);
//判断这个类是不是IRouter这个接口的子类
if (IRouter.class.isAssignableFrom(aClass)) {
//通过接口的引用 指向子类的实例
IRouter iRouter = (IRouter) aClass.newInstance();
iRouter.putClazz();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
下是完整的实现代码 ,首先我们创建一个android Library
完整的实现类
package com.hxg.lib_hrouter;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import com.hxg.lib_hrouter.contextprovider.HAppUtils;
import com.hxg.lib_hrouter.entity.ElementType;
import com.hxg.lib_hrouter.facade.Postcard;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import dalvik.system.DexFile;
/**
- 桥梁
*/
public class HRouter {
private static Handler mHandler;
private Context context;
//装在所有Activity类对象的容器
private Map<String, ElementType> map;
private HRouter() {
map = new HashMap<>();
}
public void init(Context context) {
this.context = context;
mHandler = new Handler(Looper.getMainLooper());
//根据包名获取到这个包下面所有的类名
List classList = getClassName(“com.hxg.android.hrouter.routes”);
//遍历
for (String s : classList) {
try {
Class<?> aClass = Class.forName(s);
//判断这个类是不是IRouter这个接口的子类
if (IRouter.class.isAssignableFrom(aClass)) {
//通过接口的引用 指向子类的实例
IRouter iRouter = (IRouter) aClass.newInstance();
iRouter.putClazz();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
if (HAppUtils.isApkInDebug()) {
List classLogList = getClassName(“com.hxg.android.hrouter.log”);
//遍历
for (String s : classLogList) {
try {
Class<?> aClass = Class.forName(s);
//判断这个类是不是ILog这个接口的子类
if (ILog.class.isAssignableFrom(aClass)) {
//通过接口的引用 指向子类的实例
ILog iLog = (ILog) aClass.newInstance();
iLog.logPrint();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
}
public static HRouter getInstance() {
return HrouterHolder.sInstance;
}
private static class HrouterHolder {
private static final HRouter sInstance = new HRouter();
}
public Map<String, ElementType> getMap() {
return map;
}
/**
-
将Activity,Fragment加入到map中的方法
-
@param key
-
@param clazz
*/
public void addClazz(String key, String clazzType, Class clazz) {
if (key != null && clazz != null) {
ElementType elementType = new ElementType();
elementType.setType(clazzType);
elementType.setClazz(clazz);
map.put(key, elementType);
}
}
public Postcard build(String path) {
if (TextUtils.isEmpty(path)) {
throw new RuntimeException(“HRouter 传入地址不能为空!”);
}
return new Postcard(context, path);
}
/**
-
跳转Activity的方法
-
@param currentContext
-
@param intent
-
@param requestCode
*/
public void navigation(final Context currentContext, final Intent intent, final int requestCode) {
if (!(currentContext instanceof Activity)) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
runInMainThread(new Runnable() {
@Override
public void run() {
startActivity(currentContext, intent, requestCode);
}
});
}
/**
-
跳转Activity的方法
-
@param currentContext
-
@param intent
-
@param requestCode
*/
private void startActivity(Context currentContext, Intent intent, int requestCode) {
if (requestCode >= 0) {
if (currentContext instanceof Activity) {
((Activity) currentContext).startActivityForResult(intent, requestCode);
} else {
currentContext.startActivity(intent);
}
} else {
currentContext.startActivity(intent);
}
}
/**
-
通过包名获取这个包下面的所有类名
-
@param packageName
-
@return
*/
private List getClassName(String packageName) {
//创建一个class对象集合
List classList = new ArrayList<>();
String path = null;
try {
//通过包管理器 获取到应用信息类然后获取到APK的完整路径
path = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0).sourceDir;
//根据APK的完整路径获取到编译后的dex文件目录
DexFile dexfile = new DexFile(path);
//获得编译后的dex文件中的所有class
Enumeration entries = dexfile.entries();
//然后进行遍历
while (entries.hasMoreElements()) {
//通过遍历所有的class的包名
String name = entries.nextElement();
//判断类的包名是否符合我们起的包名(com.hxg.util)
if (name.contains(packageName)) {
//如果符合,就添加到集合中
classList.add(name);
}
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return classList;
}
private void runInMainThread(Runnable runnable) {
if (Looper.getMainLooper().getThread() != Thread.currentThread()) {
mHandler.post(runnable);
} else {
runnable.run();
}
}
}
ILog接口(主要是为了在注解生成器生成代码的时保存log日志的,无实际作用)
package com.hxg.lib_hrouter;
public interface ILog {
void logPrint();
}
IRouter接口
package com.hxg.lib_hrouter;
public interface IRouter {
void putClazz();
}
Postcard(封装了参数和跳转接口)
package com.hxg.lib_hrouter.facade;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import com.hxg.lib_hrouter.HRouter;
import com.hxg.lib_hrouter.utils.SerializationUtil;
import java.io.Serializable;
import java.util.ArrayList;
public class Postcard extends RouteMeta {
private Intent mIntent;
private Context mContext;
public Postcard(Context context, String path) {
this.mContext = context;
this.mPath = path;
if (getDestination() != null) {
this.mIntent = new Intent(mContext, getDestination());
}
}
public Object navigation() {
if (getDestination() != null) {
HRouter.getInstance().navigation(mContext, mIntent, 0);
return 1;
}
if (getFragment() != null) {
try {
return getFragment().newInstance();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
return -1;
}
public Object navigation(Activity currentContext, int requestCode) {
if (getDestination() != null) {
HRouter.getInstance().navigation(currentContext, mIntent, requestCode);
return 1;
}
return -1;
}
public Postcard with(Bundle bundle) {
if (null != bundle && getDestination() != null) {
mIntent.putExtras(bundle);
}
return this;
}
public Postcard withObject(String key, Object value) {
if (getDestination() != null) {
mIntent.putExtra(key, SerializationUtil.object2Json(value));
}
return this;
}
public Postcard withString(String key, String value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withBoolean(String key, boolean value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withShort(String key, short value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withInt(String key, int value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withLong(String key, long value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withDouble(String key, double value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withByte(String key, byte value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withChar(String key, char value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withFloat(String key, float value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withCharSequence(String key, CharSequence value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withParcelable(String key, Parcelable value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withParcelableArray(String key, Parcelable[] value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withParcelableArrayList(String key, ArrayList<? extends Parcelable> value) {
if (getDestination() != null) {
mIntent.putParcelableArrayListExtra(key, value);
}
return this;
}
public Postcard withIntegerArrayList(String key, ArrayList value) {
if (getDestination() != null) {
mIntent.putIntegerArrayListExtra(key, value);
}
return this;
}
public Postcard withStringArrayList(String key, ArrayList value) {
if (getDestination() != null) {
mIntent.putStringArrayListExtra(key, value);
}
return this;
}
public Postcard withCharSequenceArrayList(String key, ArrayList value) {
if (getDestination() != null) {
mIntent.putCharSequenceArrayListExtra(key, value);
}
return this;
}
public Postcard withSerializable(String key, Serializable value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withByteArray(String key, byte[] value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withShortArray(String key, short[] value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withCharArray(String key, char[] value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withFloatArray(String key, float[] value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withCharSequenceArray(String key, CharSequence[] value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
public Postcard withBundle(String key, Bundle value) {
if (getDestination() != null) {
mIntent.putExtra(key, value);
}
return this;
}
}
RouteMeta(Postcard父类)
package com.hxg.lib_hrouter.facade;
import android.app.Activity;
import com.hxg.lib_hrouter.HRouter;
import com.hxg.lib_hrouter.entity.ElementType;
import com.hxg.lib_hrouter.utils.HToastUtil;
public class RouteMeta {
protected String mPath;
public RouteMeta() {
}
protected Class<? extends Activity> getDestination() {
ElementType elementType = HRouter.getInstance().getMap().get(mPath);
if (elementType == null) {
HToastUtil.showToast(“未找到” + mPath + “配置的类名”);
return null;
}
if (elementType.getType().equals(“activity”)) {
Class<? extends Activity> clazz = elementType.getClazz();
return clazz;
}
return null;
}
protected Class getFragment() {
ElementType elementType = HRouter.getInstance().getMap().get(mPath);
if (elementType == null) {
HToastUtil.showToast(“未找到” + mPath + “配置的类名”);
return null;
}
if (elementType.getType().equals(“fragment”)) {
Class<? extends Activity> clazz = elementType.getClazz();
return clazz;
}
return null;
}
}
ElementType(封装数据)
package com.hxg.lib_hrouter.entity;
public class ElementType {
private Class clazz;
private String type;
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return “ElementType{” +
“clazz=” + clazz +
“, type='” + type + ‘’’ +
‘}’;
}
}
其他
总结
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2019-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。祝大家2021年万事大吉。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
turn clazz;
}
return null;
}
protected Class getFragment() {
ElementType elementType = HRouter.getInstance().getMap().get(mPath);
if (elementType == null) {
HToastUtil.showToast(“未找到” + mPath + “配置的类名”);
return null;
}
if (elementType.getType().equals(“fragment”)) {
Class<? extends Activity> clazz = elementType.getClazz();
return clazz;
}
return null;
}
}
ElementType(封装数据)
package com.hxg.lib_hrouter.entity;
public class ElementType {
private Class clazz;
private String type;
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return “ElementType{” +
“clazz=” + clazz +
“, type='” + type + ‘’’ +
‘}’;
}
}
其他
总结
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2019-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
[外链图片转存中…(img-Sq09qUQ8-1715422202916)]
[外链图片转存中…(img-KBxGSfaZ-1715422202916)]
[外链图片转存中…(img-nEsd7m1j-1715422202917)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。祝大家2021年万事大吉。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!