之前想做一个支持 Material Icons (Extended) 的图标选择器。现有的实现大多是静态地维护一个图标类名列表,但这并不“优雅”。理想的做法是动态地获取图标类中的所有图标名称。
在 StackOverFlow 上找到了一个用 DexFile 动态获取包中所有类的实现:
fun getClasses(context: Context, packageName: String): List<Class<*>> {
val dexFile = DexFile(context.applicationInfo.sourceDir)
return dexFile.entries().asSequence()
.filter { it.startsWith(packageName) }
.map { context.classLoader.loadClass(it) }.toList()
}
然而,DexFile 已被弃用。故最终改用 dexlib2 来实现:
fun getClasses(context: Context, packageName: String): List<String> {
val dexFile = DexFileFactory.loadDexFile(File(context.applicationInfo.sourceDir), Opcodes.getDefault())
return dexFile.classes
.map { it.type.removePrefix("L").removeSuffix(";").replace("/", ".") }
.filter { it.startsWith(packageName) }
.map { context.classLoader.loadClass(it) }.toList()
}
这样就能动态地获取指定包中的所有类名了。也许仍然不够完美,但已经比手动维护类名列表要好得多了。