package inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
int value();
}
ContenView注解
package inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InJectView {
int value();
}
InJect注解
package inject;
import android.view.View;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventBase(listenerSetter = "setOnClickListener",listenerType = View.OnClickListener.class,callback = "onClick" )
public @interface OnClick {
int[] value();
}
package inject;
import android.view.View;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventBase(listenerSetter = "setOnLongClickListener",listenerType = View.OnLongClickListener.class,callback = "onLongClick")
public @interface OnLongClick {
int[] value();
}
onClick onLongClick注解
package inject;
import android.view.View;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventBase {
String listenerSetter();
Class<?> listenerType();
String callback();
}
事件注解 setOnClickListener View.OnClickListener,onClick
package inject;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
public class ListenerInvolcationHandler implements InvocationHandler {
private Object target;
public ListenerInvolcationHandler(Object target) {
this.target = target;
}
private HashMap methodMap = new HashMap();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(target != null){
method = (Method) methodMap.get(method.getName());
if(method != null){
method.setAccessible(true);
return method.invoke(target,args);
}
}
return null;
}
public void addMethod(String methodName,Method method){
methodMap.put(methodName,method);
}
}
package inject;
import android.app.Activity;
import android.view.View;
import com.example.aopdemo.BaseActivity;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class InjectManager {
//regesit
public static void inJect(Activity baseActivity) {
//layout
injectLayout(baseActivity);
//views
injectViews(baseActivity);
//events
injectEvent(baseActivity);
}
private static void injectEvent(Activity baseActivity) {
//registEvent
Class<? extends Activity> clazz = baseActivity.getClass();
Method[] methods = clazz.getDeclaredMethods();
if(methods != null&&methods.length >0){
for(int i = 0;i<methods.length;i++){
Method method = methods[i];
Annotation[] annotations = method.getAnnotations();
for(Annotation annotation:annotations){
Class<? > annotationType = annotation.annotationType();
if(annotationType != null){
EventBase eventBase = annotationType.getAnnotation(EventBase.class);
if(eventBase != null){
String listenerSetter = eventBase.listenerSetter();
Class<?> listenerType = eventBase.listenerType();
String callBack = eventBase.callback();
ListenerInvolcationHandler listenerInvolcationHandler = new ListenerInvolcationHandler(baseActivity);
Object listener = Proxy.newProxyInstance(listenerType.getClassLoader(),new Class[]{listenerType},listenerInvolcationHandler);
listenerInvolcationHandler.addMethod(callBack,method);
try {
Method value = annotationType.getDeclaredMethod("value");
try {
int[] ids = (int[]) value.invoke(annotation);
for(int viewId:ids){
View view = baseActivity.findViewById(viewId);
Method setter = view.getClass().getMethod(listenerSetter,listenerType);
setter.invoke(view,listener);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}
}
}
}
private static void injectViews(Activity baseActivity) {
Class<? extends Activity> clazz = baseActivity.getClass();
//get all fields
Field[] fields = clazz.getDeclaredFields();
if(fields != null&&fields.length > 0){
for(int i = 0;i< fields.length;i++){
Field field = fields[i];
InJectView inJectView = field.getAnnotation(InJectView.class);
if(inJectView != null){
try {
Method method = clazz.getMethod("findViewById", int.class);
int viewId = inJectView.value();
try {
View view = (View) method.invoke(baseActivity,viewId);
field.setAccessible(true);
field.set(baseActivity,view);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}
}
private static void injectLayout(Activity baseActivity) {
Class<? extends Activity> clazz = baseActivity.getClass();
ContentView contentView = clazz.getAnnotation(ContentView.class);
if(contentView != null){
int layout = contentView.value();
try {
Method method = clazz.getMethod("setContentView", int.class);
try {
method.invoke(baseActivity,layout);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
}
事件注解管理
package com.example.aopdemo;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import inject.InjectManager;
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
InjectManager.inJect(this);
}
}
package com.example.aopdemo;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import inject.ContentView;
import inject.InJectView;
import inject.OnClick;
import inject.OnLongClick;
@ContentView(R.layout.activity_main)
public class MainActivity extends BaseActivity {
@InJectView(R.id.bt)
private Button mBt;
@InJectView(R.id.tv)
private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
mBt.setText("test button");
mTv.setText("test text");
}
@OnClick({R.id.bt,R.id.tv})
private void onClick(View view){
switch (view.getId()){
case R.id.bt:
Log.d("zpb","onClick button");
break;
case R.id.tv:
Log.d("zpb","onClick TextView");
break;
}
}
@OnLongClick({R.id.bt})
private boolean onLongClick(View view){
switch (view.getId()){
case R.id.bt:
Log.d("zpb","onLongClick button");
break;
}
return true;
}
private void setListener(){
}
}
测试Demo