info.interfaceName = map.get('scanInterface')
def superClasses = map.get('scanSuperClasses')
if (!superClasses) {
superClasses = new ArrayList<String>()
} else if (superClasses instanceof String) {
ArrayList<String> superList = new ArrayList<>()
superList.add(superClasses)
superClasses = superList
}
info.superClassNames = superClasses
info.initClassName = map.get('codeInsertToClassName') //代码注入的类
info.initMethodName = map.get('codeInsertToMethodName') //代码注入的方法(默认为static块)
info.registerMethodName = map.get('registerMethodName') //生成的代码所调用的方法
info.registerClassName = map.get('registerClassName') //注册方法所在的类
info.include = map.get('include')
info.exclude = map.get('exclude')
info.init()
if (info.validate())
list.add(info)
else {
project.logger.error('auto register config error: scanInterface, codeInsertToClassName and registerMethodName should not be null\n' + info.toString())
}
}
if (cacheEnabled) {
checkRegisterInfo()
} else {
deleteFile(AutoRegisterHelper.getRegisterInfoCacheFile(project))
deleteFile(AutoRegisterHelper.getRegisterCacheFile(project))
}
}
##### []( )被收集的类配置:接口、基类及范围规定
> scanInterface、scanSuperClasses、include、exclude,下面内容来自框架文档
scanInterface : (必须)字符串,接口名(完整类名),所有直接实现此接口的类将会被收集
scanSuperClasses : 字符串或字符串数组,类名(完整类名),所有直接继承此类的子类将会被收集
include : 数组,需要扫描的类(正则表达式,包分隔符用/代替,如: com/billy/android/.*),默认为所有的类
exclude : 数组,不需要扫描的类(正则表达式,包分隔符用/代替,如: com/billy/android/.*),列表项(正则)匹配到最终的实现类,指定基类/接口不会对其子类/实现类生效
> 如下方法,确定扫描类列表,代码有删减:
class ScanClassVisitor extends ClassVisitor {
void visit(int version, int access, String name, String signature,
String superName, String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces)
//抽象类、接口、非public等类无法调用其无参构造方法
if (is(access, Opcodes.ACC_ABSTRACT)
|| is(access, Opcodes.ACC_INTERFACE)
|| !is(access, Opcodes.ACC_PUBLIC)
) {
return
}
infoList.each { ext ->
if (shouldProcessThisClassForRegister(ext, name)) {
if (superName != 'java/lang/Object' && !ext.superClassNames.isEmpty()) {
for (int i = 0; i < ext.superClassNames.size(); i++) {
if (ext.superClassNames.get(i) == superName) {
// println("superClassNames--------"+name)
ext.classList.add(name) //需要把对象注入到管理类 就是fileContainsInitClass
found = true
addToCacheMap(superName, name, filePath)
return
}
}
}
if (ext.interfaceName && interfaces != null) {
interfaces.each { itName ->
if (itName == ext.interfaceName) {
ext.classList.add(name)//需要把对象注入到管理类 就是fileContainsInitClass
addToCacheMap(itName, name, filePath)
found = true
}
}
}
}
}
}
}
// include和exclude的处理,exclude的优先级高于include
private static boolean shouldProcessThisClassForRegister(RegisterInfo info, String entryName) {
if (info != null) {
def list = info.includePatterns
if (list) {
def exlist = info.excludePatterns
Pattern pattern, p
for (int i = 0; i < list.size(); i++) {
pattern = (Pattern)list.get(i)
if (pattern.matcher(entryName).matches()) {
if (exlist) {
for (int j = 0; j < exlist.size(); j++) {
p = (Pattern)exlist.get(j)
if (p.matcher(entryName).matches())
return false
}
}
return true
}
}
}
}
return false
}
##### []( )管理和注册方法设置
codeInsertToClassName : (必须)字符串,类名(完整类名),通过编译时生成代码的方式将收集到的类注册到此类的codeInsertToMethodName方法中
codeInsertToMethodName: 字符串,方法名,注册代码将插入到此方法中。若未指定,则默认为static块,(方法名为:)
registerClassName: 无
registerMethodName : (必须)字符串,方法名,静态方法,方法的参数为 scanInterface
参数分为两组:**codeInsertToClassName** / **codeInsertToMethodName** 和 **registerMethodName** / **registerClassName**。
1. 第一组是管理类和管理方法:对应到示例中是 CategoryManager#initCategory
2. 第二组是注册类和注册方法:对应到示例中是 CategoryManager#register
示例中没有明确指定registerClassName,会默认赋值initClassName,也就是 **codeInsertToClassName**。所以,框架的设置中允许把管理类和注册类分开来写的。
// 代码有删减
void convertConfig() {
registerInfo.each { map ->
RegisterInfo info = new RegisterInfo()
info.initClassName = map.get('codeInsertToClassName') //代码注入的类
info.initMethodName = map.get('codeInsertToMethodName') //代码注入的方法(默认为static块)
info.registerMethodName = map.get('registerMethodName') //生成的代码所调用的方法
info.registerClassName = map.get('registerClassName') //注册方法所在的类
info.init()
}
}
void init() {
if (!registerClassName) {
registerClassName = initClassName
}
}
> 注释:从示例中可以看出 **codeInsertToMethodName** 和 **registerMethodName** 需要保持一致,同时为静态方法或者同时非静态方法;如果没有指定**codeInsertToMethodName**,默认是静态代码块,视为静态方法,此时 **registerMethodName** 需指定静态方法。
> 对于四个参数的解释,参考框架中的实现类,略有修改。从下面的代码可以看出,AutoRegister的主要作用是从不同的模块收集子类和实现类(CategoryA/CategoryB),生成注册函数(register)调用代码,插入到初始化入口函数 **initCategory()** 或 **static** 代码块。在此基础上,APP初始化时只需要调用 **initCategory()** 或者自动执行 **static** 代码块,就可以做到添加一系列实例对象到初始化列表(CATEGORIES)中,完成注册工作。
// codeInsertToClassName | registerClassName
public class CategoryManager {
private static final HashMap<String, ICategory> CATEGORIES = new HashMap<>();
// 不指定 codeInsertToMethodName 时生效
static {
register(new CategoryA()); //scanInterface的实现类
register(new CategoryB()); //scanSuperClass的子类
}
// codeInsertToMethodName
public static void initCategory() {
register(new CategoryA()); //scanInterface的实现类
register(new CategoryB()); //scanSuperClass的子类
}
// registerMethodName
static void register(ICategory category) {
if (category != null) {
CATEGORIES.put(category.getName(), category);
}
}
public static Set<String> getCategoryNames() {
return CATEGORIES.keySet();
}
}
ory) {
if (category != null) {
CATEGORIES.put(category.getName(), category);
}
}
public static Set<String> getCategoryNames() {
return CATEGORIES.keySet();
}
}
[]( )最后
==================================================================
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/190b1efe71a9a827ca37f3b676482a20.png)
![img](https://img-blog.csdnimg.cn/img_convert/081654d103f83cc7c53503e632367e86.png)
![img](https://img-blog.csdnimg.cn/img_convert/914171b71b49f25a19548cb0f9499d33.png)
![img](https://img-blog.csdnimg.cn/img_convert/a5c35e469d0d6960d2efa93bf13f28d1.png)
![img](https://img-blog.csdnimg.cn/img_convert/cc52788c8809a863da0c25a4d52a6c07.png)
![img](https://img-blog.csdnimg.cn/img_convert/a88658aa124dce9373dc062dfa6ba0e0.png)
![img](https://img-blog.csdnimg.cn/13f2cb2e05a14868a3f0fd6ac81d625c.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)**
![img](https://img-blog.csdnimg.cn/img_convert/a412f64ab9c595c0773f922bb5de109d.png)
## 推荐学习资料
* Android进阶学习全套手册
![](https://img-blog.csdnimg.cn/img_convert/94b0bf5aa09b8bc9467c9e6a1310d887.webp?x-oss-process=image/format,png)
* Android对标阿里P7学习视频
![](https://img-blog.csdnimg.cn/img_convert/a5535ac491a1bf0ff2a174f8974a1987.webp?x-oss-process=image/format,png)
* BAT TMD大厂Android高频面试题
![](https://img-blog.csdnimg.cn/img_convert/bdde4491441eaaad44cacd94b5732b31.webp?x-oss-process=image/format,png)
**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
![img](https://img-blog.csdnimg.cn/img_convert/ad4eeb5050bb0803bf0ac00e898b6c02.png)
有帮助,可以添加V获取:vip204888 (备注Android)**
[外链图片转存中...(img-SaTGEGQO-1712698906521)]
## 推荐学习资料
* Android进阶学习全套手册
[外链图片转存中...(img-twAlufiK-1712698906521)]
* Android对标阿里P7学习视频
[外链图片转存中...(img-38TUJfzf-1712698906521)]
* BAT TMD大厂Android高频面试题
[外链图片转存中...(img-mIU3yPNU-1712698906522)]
**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
[外链图片转存中...(img-Cpj1qsBm-1712698906522)]