MainActivity
@ContentView(R.layout.activity_main)
public class MainActivity extends BaseActivity{
public static final String TAG="dongnao";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ListView listView=null;
// listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
// @Override
// public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//
// }
// });
}
public void itemClick(AdapterView<?> parent, View view, int position, long id)
{
}
@OnClick({R.id.text,R.id.text2})
public void onClick(View view)
{
Toast.makeText(this,"单击",Toast.LENGTH_SHORT).show();
}
@OnLongClick({R.id.text2})
public boolean onLongClick(View view)
{
Toast.makeText(this,"长按",Toast.LENGTH_SHORT).show();
return true;
}
}
ContentView
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ContentView {
int value();
}
EventBase
/**
* Created by Administrator on 2017/2/27 0027.
* 设计目的是 对所有的事件点击 进行扩展
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface EventBase {
/**
* 设置监听的方法
* @return
*/
String listenerSetter();
/**
* 事件类型
* @return
*/
Class<?> listenerType();
/**
* 回调方法
* 事件被触发后,执行回调方法名称
*/
String callBackMethod();
}
OnClick
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@EventBase(listenerSetter = "setOnClickListener",
listenerType = View.OnClickListener.class,
callBackMethod = "onClick")
public @interface OnClick
{
/**
* 哪些kongji控件id 进行设置点击事件
* @return
*/
int[] value();
}
OnItemClick
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@EventBase(listenerSetter = "setOnClickListener",
listenerType = View.OnClickListener.class,
callBackMethod = "onClick")
public @interface OnClick
{
/**
* 哪些kongji控件id 进行设置点击事件
* @return
*/
int[] value();
}
OnLongClick
/**
* Created by Administrator on 2017/2/27 0027.
* 设置长按事件
*
* textView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return false;
}
});
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@EventBase(listenerSetter = "setOnLongClickListener",
listenerType = View.OnLongClickListener.class,callBackMethod = "onLongClick")
public @interface OnLongClick {
int[] value() default -1;
}
ListenerInvocationHandler
public class ListenerInvocationHandler implements InvocationHandler{
//activity 真实对象
private Context context;
private Map<String,Method> methodMap;
public ListenerInvocationHandler(Context context, Map<String, Method> methodMap) {
this.context = context;
this.methodMap = methodMap;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name=method.getName();
//决定是否需要进行代理
Method metf=methodMap.get(name);
if(metf!=null)
{
return metf.invoke(context,args);
}else
{
return method.invoke(proxy,args);
}
}
}
BaseActivity
public class BaseActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
InjectUtils.inject(this);
}
}
InjectUtils
/**
* Created by Administrator on 2017/2/24 0024.
* 第三方容器
*
*/
public class InjectUtils {
public static void inject(Context context)
{
injectLayout(context);
injectView(context);
injectEvents(context);
}
/**
* 注入事件
* @param context
*/
private static void injectEvents(Context context) {
Class<?> clazz=context.getClass();
//获取Activity里面 所有方法
Method[] methods=clazz.getDeclaredMethods();
//遍历Activity所有方法
for (Method method:methods)
{
//获取方法上所有的注解
Annotation[] annotations=method.getAnnotations();
for(Annotation annotation:annotations)
{
//获取注解 anntionType OnClick OnLongClck
Class<?> anntionType=annotation.annotationType();
//获取注解的注解 onClick 注解上面的EventBase
EventBase eventBase=anntionType.getAnnotation(EventBase.class);
if(eventBase==null)
{
continue;
}
/*
开始获取事件三要素 通过反射注入进去
1 listenerSetter 返回 setOnClickListener字符串
*/
String listenerSetter=eventBase.listenerSetter();
//得到 listenerType--》 View.OnClickListener.class,
Class<?> listenerType=eventBase.listenerType();
//callMethod--->onClick
String callMethod=eventBase.callBackMethod();
//方法名 与方法Method的对应关心
Map<String,Method> methodMap=new HashMap<>();
methodMap.put(callMethod,method);
try {
Method valueMethod=anntionType.getDeclaredMethod("value");
int[] viewIds= (int[]) valueMethod.invoke(annotation);
for (int viewId:viewIds)
{
//通过反射拿到TextView
Method findViewById=clazz.getMethod("findViewById",int.class);
View view= (View) findViewById.invoke(context,viewId);
if(view==null)
{
continue;
}
/*
listenerSetter setOnClickLitener
listenerType View.OnClickListener.class
*/
Method setOnClickListener=view.getClass().getMethod(listenerSetter,listenerType);
ListenerInvocationHandler handler=new ListenerInvocationHandler(context,methodMap);
// proxyy已经实现了listenerType接口
Object proxy= Proxy.newProxyInstance
(listenerType.getClassLoader(),
new Class[]{listenerType},handler);
/**
* 类比 于 textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
*/
setOnClickListener.invoke(view,proxy);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
public static void injectView(Context context)
{
Class<?> aClass=context.getClass();
//获取到MainActivity里面所有的成员变量 包含 textView
Field[] fields=aClass.getDeclaredFields();
for (Field field:fields)
{
//得到成员变量的注解
ViewInject viewInject=field.getAnnotation(ViewInject.class);
if(viewInject!=null)
{
//拿到id R.id.text
int valueId=viewInject.value();
try {
//View view=activity.findViewById()
Method method=aClass.getMethod("findViewById",int.class);
//反射调用方法
View view= (View) method.invoke(context,valueId);
field.setAccessible(true);
field.set(context,view);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
public static void injectLayout(Context context)
{
int layoutId=0;
Class<?> clazz=context.getClass();
//拿到MainActivity类上面的注解
ContentView contentView=clazz.getAnnotation(ContentView.class);
if (contentView != null ) {
layoutId=contentView.value();
try {
Method method=clazz.getMethod("setContentView",int.class);
method.invoke(context,layoutId);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}