Android知识总结
一、反射定义
反射则是一开始我们并不知道要初始化类对象是什么,自然也无法使用new关键字来创建对象。这时候,我们使用JDK提供的反射API进行反射调用。反射就是在运行状态中,对任意一个类,都能过知道这个类的所有属性和方法;对任意一个对象,都能够调用它的任意方法和属性,并改变它的属性。是Java被视为动态语言的关键。
二、反射各方法示意图
三、ASM字节码插桩
插桩就是将一段代码插入到另一段代码,或替换另一段代码。字节码插桩顾名思义就是在我们编写的源码编译成字节码(Class)后,在Android下生成dex之前修改Class文件,修改或者增强原有代码逻辑的操作。
四、动态代理
1)抽象接口
interface Api{
fun test(str : String)
}
2)真实对象
class Men : Api{
override test(str: String) {
println(str)
}
}
3)实现类
val men = Men()
val messageInterface = Proxy.newProxyInstance(
MainTest::class.java.classLoader,
arrayOf>(Api::class.java) ,
object :InvocationHandler{
override fun invoke(proxy: Any?, method: Method?, args: Array?): Any? {
return method!!.invoke(men, *(args.orEmpty()))
}
}) as Api
messageInterface.test("小米")
kotlin的可变参数和Java的可变参数转换
- (args.orEmpty()) kotlin的可变参数,并判断参数是否为空。
- args:等于Java中的可变参数(Object... args)。
-
*
号的作用是从可变参数中取出值,kotlin是可变参数传值时*
号必须写。
kotlin的可变参数和Java的可变参数转换
invoke方法的返回值可能为空,所以要将返回的Any变成Any?类型。
4)、kotlin中的泛型
- Kotlin抛弃了通配符?,直接实现了PECS的规则
等价于 <?extends T> 等价于 super T>
5)、星号投影:使用 * 代替类型参数
- 星号投影语法可以用来表名你不知道关于泛型实参的任何信息。例如,一个包含未知类型的元素的列表用这种语法表示为 List<*>。
- MutableList<> 和 MutableList
不一样,MutableList > 是包含某种特定类型元素的列表。这种列表包含的是任意类型的元素,而 MutableList<
- MutableList<> 投影成了 MutableList
:当你没有任何元素类型信息的时候,读取 Any? 类型的元素仍然是安全的,但是向列表中写入元素是不安全的。谈到 Java 通配符,Kotlin 的 AnyType< > 对应于 Java 的 MyType>。
6)、动态代理特性
实际上, Proxy.newProxyInstance 会创建一个Class,与静态代理不同,这个Class不是由具体的.java源文件编译
而来,即没有真正的文件,只是在内存中按照Class格式生成了一个Class。
String name = Api.class.getName()+"$Proxy0";
//生成代理指定接口的Class数据
byte[] bytes = ProxyGenerator.generateProxyClass(name, new Class[]{Api.class});
FileOutputStream fos = new FileOutputStream("lib/" + name+".class");
fos.write(bytes);
fos.close();
然后可以在生成的文件中查看我们的代理类:
在初始化时,获得 method 备用。而这个代理类中所有方法的实现变为:
这里的 h 其实就是 InvocationHandler 接口,所以我们在使用动态代理时,传递的 InvocationHandler 就是一个
监听,在代理对象上执行方法,都会由这个监听回调出来。
五、实现点击事件的注入
java实现
1)、定义注解
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventType {
Class listenerType();
String listenerSetter();
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventType(listenerType = View.OnClickListener.class, listenerSetter = "setOnClickListener")
public @interface OnClick {
int[] value();
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventType(listenerType = View.OnLongClickListener.class, listenerSetter = "setOnLongClickListener")
public @interface OnLongClick {
int[] value();
}
2)、实现类
public class InjectUtils {
public static void initUtils(@NotNull Activity activity) {
Class extends Activity> aClass = activity.getClass();
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method method : declaredMethods) {
//获得方法上所有注解
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations) {
Class extends Annotation> annotationType = annotation.annotationType();
if (annotationType.isAnnotationPresent(EventType.class)) {
//注解类型
EventType eventType = annotationType.getAnnotation(EventType.class);
// OnClickListener.class
Class> listenerType = eventType.listenerType();
//setOnClickListener
String listenerSetter = eventType.listenerSetter();
try {
// 不需要关心到底是OnClick 还是 OnLongClick
Method valueMethod = annotationType.getDeclaredMethod("value");
int[] viewIds = (int[]) valueMethod.invoke(annotation);
method.setAccessible(true);
ListenerInvocationHandler handler =
new ListenerInvocationHandler<>(method, activity);
Object listenerProxy = Proxy.newProxyInstance(listenerType.getClassLoader(),
new Class[]{listenerType}, handler);
// 遍历注解的值
for (int viewId : viewIds) {
// 获得当前activity的view(赋值)
View view = activity.findViewById(viewId);
// 获取指定的方法(不需要判断是Click还是LongClick)
// 如获得:setOnClickLisnter方法,参数为OnClickListener
// 获得 setOnLongClickLisnter,则参数为OnLongClickLisnter
Method setter = view.getClass().getMethod(listenerSetter, listenerType);
// 执行方法
//执行setOnclickListener里面的回调 onclick方法
setter.invoke(view, listenerProxy);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
/**
* 还可能在自定义view注入,所以是泛型: T = Activity/View
*
* @param
*/
static class ListenerInvocationHandler implements InvocationHandler {
private Method method;
private T target;
public ListenerInvocationHandler(Method method, T target) {
this.method = method;
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return this.method.invoke(target, args);
}
}
}
3)、使用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InjectUtils.injectEvent(this);
}
@OnClick({R.id.btn1, R.id.btn2})
public void click(View view) {
switch (view.getId()) {
case R.id.btn1:
Log.i(TAG, "click: 按钮1");
break;
case R.id.btn2:
Log.i(TAG, "click: 按钮2");
break;
}
}
@OnLongClick({R.id.btn1, R.id.btn2})
public boolean longClick(View view) {
switch (view.getId()) {
case R.id.btn1:
Log.i(TAG, "longClick: 按钮1");
break;
case R.id.btn2:
Log.i(TAG, "longClick: 按钮2");
break;
}
return false;
}
kotlin实现
- 1)、注解类
@Target(AnnotationTarget.ANNOTATION_CLASS)
@Retention(RetentionPolicy.RUNTIME)
annotation class EventType(
val listenerType: KClass<*>,
val listenerSetter: String
)
@Target(
AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.PROPERTY_SETTER
)
@Retention(RetentionPolicy.RUNTIME)
@EventType(listenerType = View.OnClickListener::class,
listenerSetter = "setOnClickListener")
annotation class OnClick(vararg val data: Int)
@Target(
AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.PROPERTY_SETTER
)
@Retention(RetentionPolicy.RUNTIME)
@EventType(listenerType = View.OnLongClickListener::class,
listenerSetter = "setOnLongClickListener")
annotation class OnLongClick(vararg val data : Int)
2)、实现类
object InjectUtils {
fun initUtils(activity: Activity) {
val clazz = activity::class.java
val declaredMethods = clazz.declaredMethods
for (method in declaredMethods.iterator()) {
val annotations = method.annotations
for (annotation in annotations.iterator()) {
//注解类型
val annotationType = annotation.annotationClass.javaObjectType
if (annotationType.isAnnotationPresent(EventType::class.java)) {
val eventType = annotationType.getAnnotation(EventType::class.java)
// OnClickListener.class
val listenerType = eventType.listenerType
//setOnClickListener
val listenerSetter = eventType.listenerSetter
try {
// 不需要关心到底是OnClick 还是 OnLongClick
//getDeclaredMethod 仅能获取类本身的方法(包括私有、共有、保护)
//getMethod 仅能获取类(及其父类可以自己测试) public 方法
val valueMethod = annotationType.getDeclaredMethod("data")
val viewIds = valueMethod.invoke(annotation) as IntArray
method.isAccessible = true
val handler = ListenerInvocationHandler(method, activity)
val newProxyInstance = Proxy.newProxyInstance(
listenerType.java.classLoader,
arrayOf>(listenerType.java), handler
)
for (id in viewIds.iterator()) {
val view = activity.findViewById(id)
val viewMethod = view::class.java.getMethod(
listenerSetter,
listenerType.javaObjectType)
viewMethod.invoke(view, newProxyInstance)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
}
/**
* 还可能在自定义view注入,所以是泛型: T = Activity/View
*
* @param
*/
internal class ListenerInvocationHandler : InvocationHandler {
private val method: Method
private val target: T
constructor(method: Method, target: T) {
this.method = method
this.target = target
}
override fun invoke(proxy: Any?, method: Method?, args: Array?): Any? {
return this.method.invoke(target, *(args.orEmpty()))
}
}
}
- 3)、使用
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
InjectUtils.initUtils(this@MainActivity)
}
@OnClick(data = [R.id.name_btn1, R.id.name_btn2])
fun setName1(v: View) {
when (v.id) {
R.id.name_btn1 ->
name_btn1.text = "点击我了" + a++
R.id.name_btn2 ->
name_btn2.text = "点击我了" + a++
}
}
@OnLongClick(data = [R.id.name_btn1, R.id.name_btn2])
fun setName2(v: View) : Boolean{
when (v.id) {
R.id.name_btn1 ->
name_btn1.text = "点击我了" + a++
R.id.name_btn2 ->
name_btn2.text = "点击我了" + a++
}
return false
}
利用APT技术实现的项目,源码