Android获取APK中的所有类或指定接⼝的所有实现类
⽂章⽬录
⽅案1:ServiceLoader
原理
通过将实现类的全类名写⼊特定路径的配置⽂件中, ⽣成APK会, 这些配置⽂件会进⾏合并. 读取配置⽂件中的类名, 使⽤类加载器获取Class 对象, ⽤反射其实例化.
demo
1. 整体结构
新建⼯程, 新建common模块\impl1模块\impl2模块. 其中common是放置公⽤接⼝,imp1和2放置具体的实现类. ⽅案的依赖,如下图:
注:app中⼀定要依赖所有Module, 没有依赖的Module不会参与编译, 其中的类不能被到.
...
implementation project(path: ':common') implementation project(path: ':impl1')
implementation project(path: ':impl2')
}
2. 接⼝和实现类
common中的Animal接⼝:
impl中的实现:
⼀定要在与java同级的⽂件夹建⽴/resources/META-INF/services⽬录(不是在res⽬录下),在该⽬录下创建以实现的接⼝的全名(包名+类名)为名字的⽂本⽂件, ⾥⾯是该Module中实现类的全名.
3. 查实现类
将ServiceLoader封装成了⼀个⼯具类:
/**
* 接⼝实现类⼯⼚
*
* @param <I> 要被寻实现类的接⼝
*/
public class ImplClassFactory<I> implements Iterator<I> {
private final Iterator<I> mIterator;
private final ServiceLoader<I> mLoader;
public ImplClassFactory(Class<I> interfaceClass) {
this(interfaceClass, Thread.currentThread().getContextClassLoader());
}
public ImplClassFactory(Class<I> interfaceClass, ClassLoader loader) {
if (interfaceClass == null || !interfaceClass.isInterface()) {
throw new IllegalArgumentException("interfaceClass must be a Interface!");
}
mLoader = ServiceLoader.load(interfaceClass, loader);
mIterator = mLoader.iterator();
}
public void reload() {
}
@Override
public boolean hasNext() {
return mIterator.hasNext();
}
@Override
public I next() {
();
}
}
在Activity的onCreate中遍历:
Iterator<Animal> it = new ImplClassFactory<>(Animal.class);
while (it.hasNext()) {
Log.e("animal: ", it.next().name());
}
Log输出:
可见获取了实现类的实例.
AutoService
上⾯的⽅案, 要⼿动⽣成配置⽂件, ⾮常不⽅便.
于是Google给了我们⼀个解决⽅案: 通过给实现类加注解, 编译时⾃动⽣成配置⽂件, 简化这个过程.
1. 添加依赖
// 依赖 autoService 库
implementation 'le.auto.service:auto-service:1.0-rc7'
annotationProcessor 'le.auto.service:auto-service:1.0-rc7'
需要加implementation,不然不到AutoService注解
2. 为实现类添加注解
stmon.Animal;
le.auto.service.AutoService;
//添加注解,参数是实现的接⼝类
@AutoService(Animal.class)
public class Cat implements Animal {
@Override
public String name() {
Class().getName();
}
}
这样, AutoService就会⾃动⽣成配置⽂件, 不需要我们⾃⼰创建⽬录添加配置⽂件.
使⽤fat-aar不打包配置⽂件的解决⽅案
问题: 使⽤embed引⼊的包的META-INF⽂件夹不会合并到主⼯程的aar.
但打包出来的aar还是包含有主⼯程的META-INF⽂件夹的.
解决⽅案
思路: 将引⼊的包的配置⽂件⼿动合并放到主⼯程的META-INF⽂件夹中, 从⽽打包进aar.
1. 在⼦⼯程(被embed引⼊的⼯程)中的adle中新增任务:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论