/**
* 通过反射,获取View的在res/Layout布局中声明的onClick属性名称
* 但是通过databinding方式设置的值获取不到
*
*/
fun getViewClickListenerName(view: View?): String? {
var clickName: String? = null
try {
// get the nested class `android.view.View$ListenerInfo`
val listenerInfoField: Field? = View::class.java.getDeclaredField("mListenerInfo")
listenerInfoField?.isAccessible = true
val myViewListenerInfo = listenerInfoField?.get(view)
// get the field mOnClickListener, that holds the listener and cast it to a listener
val onClickListener: Field? =
myViewListenerInfo?.javaClass?.getDeclaredField("mOnClickListener")
onClickListener?.isAccessible = true
val myClickListener = onClickListener?.get(myViewListenerInfo)
val fields = myClickListener?.javaClass?.declaredFields
fields?.apply {
for (field in fields) {
if (field.name.equals("mMethodName")) {
//get the field mMethodName
val mMethodName: Field? =
myClickListener.javaClass.getDeclaredField("mMethodName")
mMethodName?.isAccessible = true
//get my MethodName
val myMethodName = mMethodName?.get(myClickListener)
clickName = myMethodName as String?
}
}
}
} catch (e: ClassNotFoundException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
}
return clickName
}
同上一个方法:
/**
* 通过反射,获取View的在res/Layout布局中声明的onClick属性名称
*
*/
private fun getOnClickName(view: View?): String {
if (view == null) {
throw NullPointerException("view == null")
}
var Name = ""
// 反射 View.mListenerInfo.mOnClickListener.val$handlerName
try {
val mListenerInfo = getSubField(view, "mListenerInfo")
val mOnClickListener = getSubField(mListenerInfo, "mOnClickListener")
val handlerName = getSubField(mOnClickListener, "mMethodName")
Name = handlerName as String
} catch (e: Exception) {
e.printStackTrace()
}
return Name
}
/**
* 反射获取obj的成员变量fieldName(成员变量名获取,可在调试时动态查看)
*/
private fun getSubField(obj: Any?, fieldName: String): Any? {
if (obj == null) {
throw NullPointerException("obj == null")
}
var subObj: Any? = null
try {
val field: Field? = obj.javaClass.getDeclaredField(fieldName) // 获取成员变量对应的Field方法
field?.isAccessible = true // 设置为可访问
subObj = field?.get(obj) // 通过Field方法从Object中提取子变量
} catch (ex: Exception) {
ex.printStackTrace()
}
return subObj
}