更多学习和讨论,欢迎加入我们!
有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。
这里有2000+小伙伴,让你的学习不寂寞~·
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
第一步:我们新建一个 java library,搭配好相关的配置,并编写我们自定义的 Animation Seriable,如下所示
首先:我们新建一个 java library:
接着: 编写我们的自定义注解
@Documented()
// 表示是基于编译时注解的
@Retention(RetentionPolicy.CLASS)
// 表示可以作用于成员变量,类、接口
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Seriable {
}
如果对元注解还步了解的话,建议先阅读我之前写的博客 注解使用入门(一),这里不再讲解
最后:在 resources/META-INF/services/javax.annotation.processing.Processor 文件中 添加 我们自定义注解的全限定路径 com.example.JsonProcessor。注意若 resources/META-INF/services/javax.annotation.processing.Processor 不存在,需要自己添加。
第二步:编写我们的解析器,继承 AbstractProcessor ,并重写 process 方法,处理相关逻辑。
@SupportedAnnotationTypes({“com.example.Seriable”})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class JsonProcessor extends AbstractProcessor {
private Elements mElementUtils;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
// 工具辅助类
mElementUtils = processingEnv.getElementUtils();
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// 第一步,根据我们自定义的注解拿到 elememts set 集合
Set<? extends Element> elememts = roundEnv.getElementsAnnotatedWith(Seriable.class);
TypeElement typeElement;
VariableElement variableElement;
Map<String, List> map = new HashMap<>();
List fileds = null;
// 第二步: 根据 element 的类型做相应的处理,并存进 map 集合
for (Element element : elememts) {
ElementKind kind = element.getKind();
// 判断该元素是否为类
if (kind == ElementKind.CLASS) {
typeElement = (TypeElement) element;
// 这里以类的全限定类名作为 key,确保唯一
String qualifiedName = typeElement.getQualifiedName().toString();
map.put(qualifiedName, fileds = new ArrayList());
// 判断该元素是否为成员变量
} else if (kind == ElementKind.FIELD) {
variableElement = (VariableElement) element;
// 获取该元素的封装类型
typeElement = (TypeElement) variableElement.getEnclosingElement();
String qualifiedName = typeElement.getQualifiedName().toString();
fileds = map.get(qualifiedName);
if (fileds == null) {
map.put(qualifiedName, fileds = new ArrayList());
}
fileds.add(variableElement);
}
}
Set set = map.keySet();
for (String key : set) {
if (map.get(key).size() == 0) {
typeElement = mElementUtils.getTypeElement(key);
List<? extends Element> allMembers = mElementUtils.getAllMembers(typeElement);
if (allMembers.size() > 0) {
map.get(key).addAll(ElementFilter.fieldsIn(allMembers));
}
}
}
// 第三步:根据 map 集合数据生成代码
generateCodes(map);
return true;
}
// 生成我们的代码文件
private void generateCodes(Map<String, List> maps) {
File dir = new File(“f://Animation”);
if (!dir.exists())
dir.mkdirs();
// 遍历map
for (String key : maps.keySet()) {
// 创建文件
File file = new File(dir, key.replaceAll(“\.”, “_”) + “.txt”);
try {
/**
- 编写json文件内容
*/
FileWriter fw = new FileWriter(file);
fw.append(“{”).append(“class:”).append(“”" + key + “”")
.append(",\n ");
fw.append(“fields:\n {\n”);
List fields = maps.get(key);
for (int i = 0; i < fields.size(); i++) {
VariableElement field = fields.get(i);
fw.append(" “).append(field.getSimpleName()).append(”😊
.append(“”" + field.asType().toString() + “”");
if (i < fields.size() - 1) {
fw.append(“,”);
fw.append(“\n”);
}
}
fw.append(“\n }\n”);
fw.append(“}”);
fw.flush();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
思路解析
-
第一步,根据我们自定义的注解拿到 elememts set 集合
-
第二步:根据 elememt 的类型做相应的处理,并存进 map 集合
-
第三步:根据 map 集合的数据,生成相应的代码。
第三步:调用 gradle build 命令生成 jar 包
在 AndroidStudio 中的 Terminal 窗口输入 gradle build 命令,完成之后将生成 jar 包。我们就可以使用这一个 jar 包了。需要注意的是 我们需要将 gradle 添加到环境变量中。
第四步,将我们生成的 jar 包复制到 moudle 目录下,compile fileTree(dir: ‘libs’, include: [’*.jar’]) , 就可以使用了。
比如我们新建一个 moudle,新建两个类,如下:
@Seriable
public class Article {
private String title;
private String content;
}
public class User {
@Seriable()
String name;
@Seriable()
String area;
@Seriable()
int age;
int weight;
@Seriable()
List
}
在 moudle 的目录下执行 gradle build 命令,将可以在我们的保存路径中看到我们生成的两个文件,(这个路径是我们前面在编写 JsonProcessor 缩写的,File dir = new File(“f://Animation”);)
{class:“xj.jsonlibdemo.Article”,
fields:
{
title:“java.lang.String”,
content:“java.lang.String”,
time:“long”
}
尾声
评论里面有些同学有疑问关于如何学习material design控件,我的建议是去GitHub搜,有很多同行给的例子,这些栗子足够入门。
有朋友说要是动真格的话,需要NDK以及JVM等的知识,首现**NDK并不是神秘的东西,**你跟着官方的步骤走一遍就知道什么回事了,无非就是一些代码格式以及原生/JAVA内存交互,进阶一点的有原生/JAVA线程交互,线程交互确实有点蛋疼,但平常避免用就好了,再说对于初学者来说关心NDK干嘛,据鄙人以前的经历,只在音视频通信和一个嵌入式信号处理(离线)的两个项目中用过,嵌入式信号处理是JAVA->NDK->.SO->MATLAB这样调用的我原来MATLAB的代码,其他的大多就用在游戏上了吧,一般的互联网公司会有人给你公司的SO包的。
至于JVM,该掌握的那部分,相信我,你会掌握的,不该你掌握的,有那些专门研究JVM的人来做,不如省省心有空看看计算机系统,编译原理。
一句话,平常多写多练,这是最基本的程序员的素质,尽量挤时间,读理论基础书籍,JVM不是未来30年唯一的虚拟机,JAVA也不一定再风靡未来30年工业界,其他的系统和语言也会雨后春笋冒出来,但你理论扎实会让你很快理解学会一个语言或者框架,你平常写的多会让你很快熟练的将新学的东西应用到实际中。
初学者,一句话,多练。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
译原理。**
一句话,平常多写多练,这是最基本的程序员的素质,尽量挤时间,读理论基础书籍,JVM不是未来30年唯一的虚拟机,JAVA也不一定再风靡未来30年工业界,其他的系统和语言也会雨后春笋冒出来,但你理论扎实会让你很快理解学会一个语言或者框架,你平常写的多会让你很快熟练的将新学的东西应用到实际中。
初学者,一句话,多练。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!