第一个部分- XUtils框架2.0实现:事件注入、资源注入、保存数据注入
1、注入事件
XUtils2.0框架实现
import android.app.Activity;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.view.View;
import com.lidroid.xutils.util.LogUtils;
import com.lidroid.xutils.view.EventListenerManager;
import com.lidroid.xutils.view.ResLoader;
import com.lidroid.xutils.view.ViewFinder;
import com.lidroid.xutils.view.ViewInjectInfo;
import com.lidroid.xutils.view.annotation.ContentView;
import com.lidroid.xutils.view.annotation.PreferenceInject;
import com.lidroid.xutils.view.annotation.ResInject;
import com.lidroid.xutils.view.annotation.ViewInject;
import com.lidroid.xutils.view.annotation.event.EventBase;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ViewUtils {
private ViewUtils() {
}
public static void inject(View view) {
injectObject(view, new ViewFinder(view));
}
public static void inject(Activity activity) {
injectObject(activity, new ViewFinder(activity));
}
public static void inject(PreferenceActivity preferenceActivity) {
injectObject(preferenceActivity, new ViewFinder(preferenceActivity));
}
public static void inject(Object handler, View view) {
injectObject(handler, new ViewFinder(view));
}
public static void inject(Object handler, Activity activity) {
injectObject(handler, new ViewFinder(activity));
}
public static void inject(Object handler, PreferenceGroup preferenceGroup) {
injectObject(handler, new ViewFinder(preferenceGroup));
}
public static void inject(Object handler, PreferenceActivity preferenceActivity) {
injectObject(handler, new ViewFinder(preferenceActivity));
}
@SuppressWarnings("ConstantConditions")
private static void injectObject(Object handler, ViewFinder finder) {
Class<?> handlerType = handler.getClass();
// inject ContentView
ContentView contentView = handlerType.getAnnotation(ContentView.class);
if (contentView != null) {
try {
Method setContentViewMethod = handlerType.getMethod("setContentView", int.class);
setContentViewMethod.invoke(handler, contentView.value());
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
}
// inject view
Field[] fields = handlerType.getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
ViewInject viewInject = field.getAnnotation(ViewInject.class);
if (viewInject != null) {
try {
View view = finder.findViewById(viewInject.value(), viewInject.parentId());
if (view != null) {
field.setAccessible(true);
field.set(handler, view);
}
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
} else {
ResInject resInject = field.getAnnotation(ResInject.class);
if (resInject != null) {
try {
Object res = ResLoader.loadRes(
resInject.type(), finder.getContext(), resInject.id());
if (res != null) {
field.setAccessible(true);
field.set(handler, res);
}
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
} else {
PreferenceInject preferenceInject = field.getAnnotation(PreferenceInject.class);
if (preferenceInject != null) {
try {
Preference preference = finder.findPreference(preferenceInject.value());
if (preference != null) {
field.setAccessible(true);
field.set(handler, preference);
}
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
}
}
}
}
}
// inject event
Method[] methods = handlerType.getDeclaredMethods();
if (methods != null && methods.length > 0) {
for (Method method : methods) {
Annotation[] annotations = method.getDeclaredAnnotations();
//便利注解目的:为了获取我们想要的注解对象
if (annotations != null && annotations.length > 0) {
for (Annotation annotation : annotations) {
//获取注解类型
Class<?> annType = annotation.annotationType();
if (annType.getAnnotation(EventBase.class) != null) {
method.setAccessible(true);
try {
// ProGuard:-keep class * extends java.lang.annotation.Annotation { *; }
Method valueMethod = annType.getDeclaredMethod("value");
Method parentIdMethod = null;
try {
parentIdMethod = annType.getDeclaredMethod("parentId");
} catch (Throwable e) {
}
//获取OnClick、OnLongClick......注解身上的value方法
//values说白了就是控件的id数组
Object values = valueMethod.invoke(annotation);
Object parentIds = parentIdMethod == null ? null : parentIdMethod.invoke(annotation);
int parentIdsLen = parentIds == null ? 0 : Array.getLength(parentIds);
//获取数组长度
int len = Array.getLength(values);
//遍历id数组
for (int i = 0; i < len; i++) {
ViewInjectInfo info = new ViewInjectInfo();
//获取数组中试图的id(一个的id)
info.value = Array.get(values, i);
info.parentId = parentIdsLen > i ? (Integer) Array.get(parentIds, i) : 0;
EventListenerManager.addEventMethod(finder, info, annotation, handler, method);
}
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
}
}
}
}
}
}
}
绑定事件(通过动态代理实现) EventListenerManager.Java
import android.view.View;
import com.lidroid.xutils.util.LogUtils;
import com.lidroid.xutils.util.DoubleKeyValueMap;
import com.lidroid.xutils.view.annotation.event.EventBase;
import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
public class EventListenerManager {
private EventListenerManager() {
}
/**
* k1: viewInjectInfo
* k2: interface Type
* value: listener
*/
private final static DoubleKeyValueMap<ViewInjectInfo, Class<?>, Object> listenerCache =
new DoubleKeyValueMap<ViewInjectInfo, Class<?>, Object>();
public static void addEventMethod(
ViewFinder finder,
ViewInjectInfo info,
Annotation eventAnnotation,
Object handler,
Method method) {
try {
View view = finder.findViewByInfo(info);
if (view != null) {
EventBase eventBase = eventAnnotation.annotationType().getAnnotation(EventBase.class);
//监听类型:OnClickListener、OnTouchListener、OnLongClickListener......
Class<?> listenerType = eventBase.listenerType();
//事件源(你要给那个View绑定监听,而且该监听对应的方法)
//View.setOnClickListener() View.setOnTouchListener view.setOnLongClickListener
String listenerSetter = eventBase.listenerSetter();
//监听方法:onClick方法、onTouch方法、onLongClick方法
String methodName = eventBase.methodName();
//addNewMethod该属性作用:控制是否需要创建代理对象,如果缓存存在,我们不需要创建,不存在则创建
//false:代表创建 true:代表不创建
boolean addNewMethod = false;
//从缓存中获取提高了性能、节约了性能
Object listener = listenerCache.get(info, listenerType);
DynamicHandler dynamicHandler = null;
if (listener != null) {
dynamicHandler = (DynamicHandler) Proxy.getInvocationHandler(listener);
addNewMethod = handler.equals(dynamicHandler.getHandler());
if (addNewMethod) {
dynamicHandler.addMethod(methodName, method);
}
}
if (!addNewMethod) {
//第一次添加监听
dynamicHandler = new DynamicHandler(handler);
dynamicHandler.addMethod(methodName, method);
//listener:代理对象
listener = Proxy.newProxyInstance(
listenerType.getClassLoader(),
new Class<?>[]{listenerType},
dynamicHandler);
//缓存
listenerCache.put(info, listenerType, listener);
}
//绑定监听
Method setEventListenerMethod = view.getClass().getMethod(listenerSetter, listenerType);
setEventListenerMethod.invoke(view, listener);
}
} catch (Throwable e) {
LogUtils.e(e.getMessage(), e);
}
}
//WeakReference?为什么?
//第一点:及时清理内存
//第二点:Activity很有可能会被意外释放(意外关闭,而这个时候你刚好执行代码到了控件的加载)
//添加弱引用目的:为了防止对象意外被释放关闭而产生异常(典型:空指针异常)
public static class DynamicHandler implements InvocationHandler {
private WeakReference<Object> handlerRef;
private final HashMap<String, Method> methodMap = new HashMap<String, Method>(1);
//动态代理 持有目标对象:代表Activity或者Fragment
public DynamicHandler(Object handler) {
this.handlerRef = new WeakReference<Object>(handler);
}
public void addMethod(String name, Method method) {
methodMap.put(name, method);
}
public Object getHandler() {
return handlerRef.get();
}
public void setHandler(Object handler) {
this.handlerRef = new WeakReference<Object>(handler);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object handler = handlerRef.get();
if (handler != null) {
String methodName = method.getName();
method = methodMap.get(methodName);
//目的:确定代理需要的方法
if (method != null) {
return method.invoke(handler, args);
}
}
return null;
}
}
}
ViewInjectInfo类作用保存控件id类
将来我要扩展该类的属性 控制功能逻辑
public class ViewInjectInfo {
public Object value;
public int parentId;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ViewInjectInfo)) return false;
ViewInjectInfo that = (ViewInjectInfo) o;
if (parentId != that.parentId) return false;
if (value == null) return (null == that.value);
return value.equals(that.value);
}
@Override
public int hashCode() {
int result = value.hashCode();
result = 31 * result + parentId;
return result;
}
}
2.优化一下
优化第一步:设置方法访问权限:method.setAccessible(true); 允许访问 private形式
优化第二步:缓存优化
缺陷:注解类过于庞大。 框架变得越来越臃肿
第二个部分:XUtils框架3.0实现核心架构原理:整体架构做了重写
就一个模块进行分析(ViewUtils模块)
问题:我们Android有多少个监听,你就要定义多少个注解类?(XUtils2.0实现)
2.0注解类过于庞大。 框架变得越来越臃肿
XUtils3.0之后整体架构大的改进和升级
四大接口模块都通过简单工厂类获取,同受采用了静态内部类单例模式
package org.xutils;
import android.app.Application;
import android.content.Context;
import org.xutils.common.TaskController;
import org.xutils.common.task.TaskControllerImpl;
import org.xutils.db.DbManagerImpl;
import org.xutils.http.HttpManagerImpl;
import org.xutils.image.ImageManagerImpl;
import org.xutils.view.ViewInjectorImpl;
import java.lang.reflect.Method;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
/**
* Created by wyouflf on 15/6/10.
* 任务控制中心, http, image, db, view注入等接口的入口.
* 需要在在application的onCreate中初始化: x.Ext.init(this);
*/
public final class x {
private x() {
}
public static boolean isDebug() {
return Ext.debug;
}
public static Application app() {
if (Ext.app == null) {
try {
// 在IDE进行布局预览时使用
Class<?> renderActionClass = Class.forName("com.android.layoutlib.bridge.impl.RenderAction");
Method method = renderActionClass.getDeclaredMethod("getCurrentContext");
Context context = (Context) method.invoke(null);
Ext.app = new MockApplication(context);
} catch (Throwable ignored) {
throw new RuntimeException("please invoke x.Ext.init(app) on Application#onCreate()"
+ " and register your Application in manifest.");
}
}
return Ext.app;
}
public static TaskController task() {
return Ext.taskController;
}
public static HttpManager http() {
if (Ext.httpManager == null) {
HttpManagerImpl.registerInstance();
}
return Ext.httpManager;
}
public static ImageManager image() {
if (Ext.imageManager == null) {
ImageManagerImpl.registerInstance();
}
return Ext.imageManager;
}
public static ViewInjector view() {
if (Ext.viewInjector == null) {
ViewInjectorImpl.registerInstance();
}
return Ext.viewInjector;
}
public static DbManager getDb(DbManager.DaoConfig daoConfig) {
return DbManagerImpl.getInstance(daoConfig);
}
//静态内部类单例模式
public static class Ext {
private static boolean debug;
private static Application app;
private static TaskController taskController;
private static HttpManager httpManager;
private static ImageManager imageManager;
private static ViewInjector viewInjector;
private Ext() {
}
public static void init(Application app) {
TaskControllerImpl.registerInstance();
if (Ext.app == null) {
Ext.app = app;
}
}
public static void setDebug(boolean debug) {
Ext.debug = debug;
}
public static void setTaskController(TaskController taskController) {
if (Ext.taskController == null) {
Ext.taskController = taskController;
}
}
public static void setHttpManager(HttpManager httpManager) {
Ext.httpManager = httpManager;
}
public static void setImageManager(ImageManager imageManager) {
Ext.imageManager = imageManager;
}
public static void setViewInjector(ViewInjector viewInjector) {
Ext.viewInjector = viewInjector;
}
public static void setDefaultHostnameVerifier(HostnameVerifier hostnameVerifier) {
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
}
}
private static class MockApplication extends Application {
public MockApplication(Context baseContext) {
this.attachBaseContext(baseContext);
}
}
}
ViewUtils模块为例:
第一个优化改进:整体架构(采用面向接口编程 同时采用了一些设计模式)
第二个优化改进:ViewUtils事件注解结构类进行了改进(由用户配置)
将所有注解事件进行了合并,有用户指定对应的监听
默认是OnClickListener监听
性能提高了(之前是嵌套循环)
ViewInjectorImpl.java
/*
* Copyright (c) 2013. wyouflf (wyouflf@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xutils.view;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.xutils.ViewInjector;
import org.xutils.common.util.LogUtil;
import org.xutils.view.annotation.ContentView;
import org.xutils.view.annotation.Event;
import org.xutils.view.annotation.ViewInject;
import org.xutils.x;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashSet;
public final class ViewInjectorImpl implements ViewInjector {
private static final HashSet<Class<?>> IGNORED = new HashSet<Class<?>>();
static {
IGNORED.add(Object.class);
IGNORED.add(Activity.class);
IGNORED.add(android.app.Fragment.class);
try {
IGNORED.add(Class.forName("android.support.v4.app.Fragment"));
IGNORED.add(Class.forName("android.support.v4.app.FragmentActivity"));
} catch (Throwable ignored) {
}
}
private static final Object lock = new Object();
private static volatile ViewInjectorImpl instance;
private ViewInjectorImpl() {
}
public static void registerInstance() {
if (instance == null) {
synchronized (lock) {
if (instance == null) {
instance = new ViewInjectorImpl();
}
}
}
x.Ext.setViewInjector(instance);
}
@Override
public void inject(View view) {
injectObject(view, view.getClass(), new ViewFinder(view));
}
@Override
public void inject(Activity activity) {
//获取Activity的ContentView的注解
Class<?> handlerType = activity.getClass();
try {
ContentView contentView = findContentView(handlerType);
if (contentView != null) {
int viewId = contentView.value();
if (viewId > 0) {
Method setContentViewMethod = handlerType.getMethod("setContentView", int.class);
setContentViewMethod.invoke(activity, viewId);
}
}
} catch (Throwable ex) {
LogUtil.e(ex.getMessage(), ex);
}
injectObject(activity, handlerType, new ViewFinder(activity));
}
@Override
public void inject(Object handler, View view) {
injectObject(handler, handler.getClass(), new ViewFinder(view));
}
@Override
public View inject(Object fragment, LayoutInflater inflater, ViewGroup container) {
// inject ContentView
View view = null;
Class<?> handlerType = fragment.getClass();
try {
ContentView contentView = findContentView(handlerType);
if (contentView != null) {
int viewId = contentView.value();
if (viewId > 0) {
view = inflater.inflate(viewId, container, false);
}
}
} catch (Throwable ex) {
LogUtil.e(ex.getMessage(), ex);
}
// inject res & event
injectObject(fragment, handlerType, new ViewFinder(view));
return view;
}
/**
* 从父类获取注解View
*/
private static ContentView findContentView(Class<?> thisCls) {
if (thisCls == null || IGNORED.contains(thisCls)) {
return null;
}
ContentView contentView = thisCls.getAnnotation(ContentView.class);
if (contentView == null) {
return findContentView(thisCls.getSuperclass());
}
return contentView;
}
@SuppressWarnings("ConstantConditions")
private static void injectObject(Object handler, Class<?> handlerType, ViewFinder finder) {
if (handlerType == null || IGNORED.contains(handlerType)) {
return;
}
// 从父类到子类递归
injectObject(handler, handlerType.getSuperclass(), finder);
// inject view
Field[] fields = handlerType.getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
Class<?> fieldType = field.getType();
if (
/* 不注入静态字段 */ Modifier.isStatic(field.getModifiers()) ||
/* 不注入final字段 */ Modifier.isFinal(field.getModifiers()) ||
/* 不注入基本类型字段 */ fieldType.isPrimitive() ||
/* 不注入数组类型字段 */ fieldType.isArray()) {
continue;
}
ViewInject viewInject = field.getAnnotation(ViewInject.class);
if (viewInject != null) {
try {
View view = finder.findViewById(viewInject.value(), viewInject.parentId());
if (view != null) {
field.setAccessible(true);
field.set(handler, view);
} else {
throw new RuntimeException("Invalid @ViewInject for "
+ handlerType.getSimpleName() + "." + field.getName());
}
} catch (Throwable ex) {
LogUtil.e(ex.getMessage(), ex);
}
}
}
} // end inject view
// inject event
Method[] methods = handlerType.getDeclaredMethods();
if (methods != null && methods.length > 0) {
for (Method method : methods) {
//注意:静态方法不允许添加控件注解,私有方法允许访问,非私有方法不允许访问
if (Modifier.isStatic(method.getModifiers())
|| !Modifier.isPrivate(method.getModifiers())) {
continue;
}
//检查当前方法是否是event注解的方法
Event event = method.getAnnotation(Event.class);
if (event != null) {
try {
// id参数
int[] values = event.value();
int[] parentIds = event.parentId();
int parentIdsLen = parentIds == null ? 0 : parentIds.length;
//循环所有id,生成ViewInfo并添加代理反射
for (int i = 0; i < values.length; i++) {
int value = values[i];
if (value > 0) {
ViewInfo info = new ViewInfo();
info.value = value;
info.parentId = parentIdsLen > i ? parentIds[i] : 0;
method.setAccessible(true);
EventListenerManager.addEventMethod(finder, info, event, handler, method);
}
}
} catch (Throwable ex) {
LogUtil.e(ex.getMessage(), ex);
}
}
}
} // end inject event
}
}
在xUtils框架3.0之后,要求我们的方法必须是私有方法(注意:public不行)
让注解方法只属于当前类
//注意:静态方法不允许添加控件注解,私有方法允许访问,非私有方法不允许访问
if (Modifier.isStatic(method.getModifiers())
|| !Modifier.isPrivate(method.getModifiers())) {
continue;
}
/*
* Copyright (c) 2013. wyouflf (wyouflf@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.xutils.view;
import android.text.TextUtils;
import android.view.View;
import org.xutils.common.util.DoubleKeyValueMap;
import org.xutils.common.util.LogUtil;
import org.xutils.view.annotation.Event;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
/*package*/ final class EventListenerManager {
private final static long QUICK_EVENT_TIME_SPAN = 300;
private final static HashSet<String> AVOID_QUICK_EVENT_SET = new HashSet<String>(2);
static {
AVOID_QUICK_EVENT_SET.add("onClick");
AVOID_QUICK_EVENT_SET.add("onItemClick");
}
private EventListenerManager() {
}
/**
* k1: viewInjectInfo
* k2: interface Type
* value: listener
*/
private final static DoubleKeyValueMap<ViewInfo, Class<?>, Object>
listenerCache = new DoubleKeyValueMap<ViewInfo, Class<?>, Object>();
public static void addEventMethod(
//根据页面或view holder生成的ViewFinder
ViewFinder finder,
//根据当前注解ID生成的ViewInfo
ViewInfo info,
//注解对象
Event event,
//页面或view holder对象
Object handler,
//当前注解方法
Method method) {
try {
View view = finder.findViewByInfo(info);
if (view != null) {
// 注解中定义的接口,比如Event注解默认的接口为View.OnClickListener
Class<?> listenerType = event.type();
// 默认为空,注解接口对应的Set方法,比如setOnClickListener方法
String listenerSetter = event.setter();
if (TextUtils.isEmpty(listenerSetter)) {
listenerSetter = "set" + listenerType.getSimpleName();
}
String methodName = event.method();
boolean addNewMethod = false;
/*
根据View的ID和当前的接口类型获取已经缓存的接口实例对象,
比如根据View.id和View.OnClickListener.class两个键获取这个View的OnClickListener对象
*/
Object listener = listenerCache.get(info, listenerType);
DynamicHandler dynamicHandler = null;
/*
如果接口实例对象不为空
获取接口对象对应的动态代理对象
如果动态代理对象的handler和当前handler相同
则为动态代理对象添加代理方法
*/
if (listener != null) {
dynamicHandler = (DynamicHandler) Proxy.getInvocationHandler(listener);
addNewMethod = handler.equals(dynamicHandler.getHandler());
if (addNewMethod) {
dynamicHandler.addMethod(methodName, method);
}
}
// 如果还没有注册此代理
if (!addNewMethod) {
dynamicHandler = new DynamicHandler(handler);
dynamicHandler.addMethod(methodName, method);
// 生成的代理对象实例,比如View.OnClickListener的实例对象
listener = Proxy.newProxyInstance(
listenerType.getClassLoader(),
new Class<?>[]{listenerType},
dynamicHandler);
listenerCache.put(info, listenerType, listener);
}
Method setEventListenerMethod = view.getClass().getMethod(listenerSetter, listenerType);
setEventListenerMethod.invoke(view, listener);
}
} catch (Throwable ex) {
LogUtil.e(ex.getMessage(), ex);
}
}
public static class DynamicHandler implements InvocationHandler {
// 存放代理对象,比如Fragment或view holder
private WeakReference<Object> handlerRef;
// 存放代理方法
private final HashMap<String, Method> methodMap = new HashMap<String, Method>(1);
private static long lastClickTime = 0;
public DynamicHandler(Object handler) {
this.handlerRef = new WeakReference<Object>(handler);
}
public void addMethod(String name, Method method) {
methodMap.put(name, method);
}
public Object getHandler() {
return handlerRef.get();
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object handler = handlerRef.get();
if (handler != null) {
String eventMethod = method.getName();
if ("toString".equals(eventMethod)) {
return DynamicHandler.class.getSimpleName();
}
method = methodMap.get(eventMethod);
if (method == null && methodMap.size() == 1) {
for (Map.Entry<String, Method> entry : methodMap.entrySet()) {
if (TextUtils.isEmpty(entry.getKey())) {
method = entry.getValue();
}
break;
}
}
if (method != null) {
if (AVOID_QUICK_EVENT_SET.contains(eventMethod)) {
long timeSpan = System.currentTimeMillis() - lastClickTime;
if (timeSpan < QUICK_EVENT_TIME_SPAN) {
LogUtil.d("onClick cancelled: " + timeSpan);
return null;
}
lastClickTime = System.currentTimeMillis();
}
try {
return method.invoke(handler, args);
} catch (Throwable ex) {
throw new RuntimeException("invoke method error:" +
handler.getClass().getName() + "#" + method.getName(), ex);
}
} else {
LogUtil.w("method not impl: " + eventMethod + "(" + handler.getClass().getSimpleName() + ")");
}
}
return null;
}
}
}
简化Activity中得监听事件语句
// 注解中定义的接口,比如Event注解默认的接口为View.OnClickListener
Class<?> listenerType = event.type();
// 默认为空,注解接口对应的Set方法,比如setOnClickListener方法
String listenerSetter = event.setter();
if (TextUtils.isEmpty(listenerSetter)) {
listenerSetter = "set" + listenerType.getSimpleName();
}
否则 我们要在Activity中这么写
@Event(listenerType = View.OnTouchListener.class, callbackMethod = "onTouch",listenerSetter = "setOnTouchListener",value={R.id.tv_title})
private boolean touch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Toast.makeText(this, "触摸按下!", Toast.LENGTH_LONG).show();
break;
default:
break;
}
return true;
}
网友评论