一些不常见的场景,获取到的资源是服务端下发字符串 "R.layout.sleep_activity","R.anim.fly_up"形式。
或者写Demo的时候,一个Activity对应多个布局,希望以外部传入字符串形式设置 setContentView(layout)。比如以下:
传递给目标Activity一个字符串“R.layout.xxx”,而本地对应的布局xxx有多个,需要加载到同一个目标Activity
方法之一是通过反射,从R资源类获取想要的“R.layout.xxx” 的int值,再setContentView(it)
/**
* 应用:
* val layoutIdInt = Util.getIdByName(context, "layout", "R.layout.sleep_activity")
* */
fun getIdByName(context: Context, typeName: String, name: String): Int {
val packageName = context.packageName
var id = 0
try {
val r = Class.forName("$packageName.R")
val resTypes = r.classes
var dstClass: Class<*>? = null
// Search if has type we need?
for (i in resTypes.indices) {
// resTypes[i] is the type of resource, eg. "com.jesen.cod.layoutadvanced.R$anim"
// end is typeName, eg. "anim"
val end = resTypes[i].name.split("\\$").toTypedArray()[1]
if (end == typeName) {
dstClass = resTypes[i]
break
}
}
// Yes, find the type
if (dstClass != null) {
val simpleName = name.split("\\.").toTypedArray()[2]
val f = dstClass.getField(simpleName)
//f.setAccessible(true);
Log.d("XXX", "getIdByName, f : $f")
id = f.getInt(dstClass)
}
} catch (e: ClassNotFoundException) {
e.printStackTrace()
} catch (e: IllegalArgumentException) {
e.printStackTrace()
} catch (e: SecurityException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
} catch (e: NoSuchFieldException) {
e.printStackTrace()
}
return id
}
网友评论