和UI控件绑定原理类似,UI和事件绑定也是通过注解Annatation和反射实现的,都是通过方法名然后使用反射的invoke方法。
1 写法一:http://www.jianshu.com/p/9bee8e143410,该方法需要实现用于注解方法的Annotation,然后对该类的方法进行扫描,从而找到具实现点击事件的方法
public class PanViewInjector {
public static void process(final Object o) {
Class c = o.getClass();
Method[] methods = c.getDeclaredMethods();
for (final Method m : methods) {
OnClick click = m.getAnnotation(OnClick.class);//通过反射api获取方法上面的注解
if (click != null) {
if (o instanceof Activity) {
if (click.value() == -1) return;
View view = ((Activity) o).findViewById(click.value());//通过注解的值获取View控件
if (view == null) return;
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
m.invoke(o);//通过反射来调用被注解修饰的方法
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
}
}
}
最后在Activity里面使用注解,并在Oncreate里面调用PanViewInjector.process()
public class MainActivity extends AppCompatActivity {
@OnClick(R.id.centerButton)//使用注解
public void toCenter(){
Toast.makeText(this,"注解起作用啦",Toast.LENGTH_SHORT).show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PanViewInjector.process(this);//调用注解处理器
}
}
写法二:Afinal原理:https://github.com/yangfuhai/afinal/blob/master/src/net/tsz/afinal/FinalActivity.java
Afinal是通过在UI的变量名称上直接绑定的一个方法名称,与方法一相比,不用扫描整个类中的方法来找到与事件相关的方法。Afinal适用一个控件一个方法,方法一可应用于多个应用对应一个方法。
public abstract class FinalActivity extends Activity {
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
initInjectedView(this);
}
public void setContentView(View view, LayoutParams params) {
super.setContentView(view, params);
initInjectedView(this);
}
public void setContentView(View view) {
super.setContentView(view);
initInjectedView(this);
}
public static void initInjectedView(Activity activity){
initInjectedView(activity, activity.getWindow().getDecorView());
}
public static void initInjectedView(Object injectedSource,View sourceView){
Field[] fields = injectedSource.getClass().getDeclaredFields();
if(fields!=null && fields.length>0){
for(Field field : fields){
try {
field.setAccessible(true);
if(field.get(injectedSource)!= null )
continue;
ViewInject viewInject = field.getAnnotation(ViewInject.class);
if(viewInject!=null){
int viewId = viewInject.id();
field.set(injectedSource,sourceView.findViewById(viewId));
setListener(injectedSource,field,viewInject.click(),Method.Click);
setListener(injectedSource,field,viewInject.longClick(),Method.LongClick);
setListener(injectedSource,field,viewInject.itemClick(),Method.ItemClick);
setListener(injectedSource,field,viewInject.itemLongClick(),Method.itemLongClick);
Select select = viewInject.select();
if(!TextUtils.isEmpty(select.selected())){
setViewSelectListener(injectedSource,field,select.selected(),select.noSelected());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private static void setViewSelectListener(Object injectedSource,Field field,String select,String noSelect)throws Exception{
Object obj = field.get(injectedSource);
if(obj instanceof View){
((AbsListView)obj).setOnItemSelectedListener(new EventListener(injectedSource).select(select).noSelect(noSelect));
}
}
private static void setListener(Object injectedSource,Field field,String methodName,Method method)throws Exception{
if(methodName == null || methodName.trim().length() == 0)
return;
Object obj = field.get(injectedSource);
switch (method) {
case Click:
if(obj instanceof View){
((View)obj).setOnClickListener(new EventListener(injectedSource).click(methodName));
}
break;
case ItemClick:
if(obj instanceof AbsListView){
((AbsListView)obj).setOnItemClickListener(new EventListener(injectedSource).itemClick(methodName));
}
break;
case LongClick:
if(obj instanceof View){
((View)obj).setOnLongClickListener(new EventListener(injectedSource).longClick(methodName));
}
break;
case itemLongClick:
if(obj instanceof AbsListView){
((AbsListView)obj).setOnItemLongClickListener(new EventListener(injectedSource).itemLongClick(methodName));
}
break;
default:
break;
}
}
public enum Method{
Click,LongClick,ItemClick,itemLongClick
}
EventListener.java
package net.tsz.afinal.annotation.view;
import java.lang.reflect.Method;
import net.tsz.afinal.exception.ViewException;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
public class EventListener implements OnClickListener, OnLongClickListener, OnItemClickListener, OnItemSelectedListener,OnItemLongClickListener {
private Object handler;
private String clickMethod;
private String longClickMethod;
private String itemClickMethod;
private String itemSelectMethod;
private String nothingSelectedMethod;
private String itemLongClickMehtod;
public EventListener(Object handler) {
this.handler = handler;
}
public EventListener click(String method){
this.clickMethod = method;
return this;
}
public EventListener longClick(String method){
this.longClickMethod = method;
return this;
}
public EventListener itemLongClick(String method){
this.itemLongClickMehtod = method;
return this;
}
public EventListener itemClick(String method){
this.itemClickMethod = method;
return this;
}
public EventListener select(String method){
this.itemSelectMethod = method;
return this;
}
public EventListener noSelect(String method){
this.nothingSelectedMethod = method;
return this;
}
public boolean onLongClick(View v) {
return invokeLongClickMethod(handler,longClickMethod,v);
}
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
return invokeItemLongClickMethod(handler,itemLongClickMehtod,arg0,arg1,arg2,arg3);
}
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
invokeItemSelectMethod(handler,itemSelectMethod,arg0,arg1,arg2,arg3);
}
public void onNothingSelected(AdapterView<?> arg0) {
invokeNoSelectMethod(handler,nothingSelectedMethod,arg0);
}
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
invokeItemClickMethod(handler,itemClickMethod,arg0,arg1,arg2,arg3);
}
public void onClick(View v) {
invokeClickMethod(handler, clickMethod, v);
}
private static Object invokeClickMethod(Object handler, String methodName, Object... params){
if(handler == null) return null;
Method method = null;
try{
method = handler.getClass().getDeclaredMethod(methodName,View.class);
if(method!=null)
return method.invoke(handler, params);
else
throw new ViewException("no such method:"+methodName);
}catch(Exception e){
e.printStackTrace();
}
return null;
}
private static boolean invokeLongClickMethod(Object handler, String methodName, Object... params){
if(handler == null) return false;
Method method = null;
try{
//public boolean onLongClick(View v)
method = handler.getClass().getDeclaredMethod(methodName,View.class);
if(method!=null){
Object obj = method.invoke(handler, params);
return obj==null?false:Boolean.valueOf(obj.toString());
}
else
throw new ViewException("no such method:"+methodName);
}catch(Exception e){
e.printStackTrace();
}
return false;
}
private static Object invokeItemClickMethod(Object handler, String methodName, Object... params){
if(handler == null) return null;
Method method = null;
try{
///onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
method = handler.getClass().getDeclaredMethod(methodName,AdapterView.class,View.class,int.class,long.class);
if(method!=null)
return method.invoke(handler, params);
else
throw new ViewException("no such method:"+methodName);
}catch(Exception e){
e.printStackTrace();
}
return null;
}
private static boolean invokeItemLongClickMethod(Object handler, String methodName, Object... params){
if(handler == null) throw new ViewException("invokeItemLongClickMethod: handler is null :");
Method method = null;
try{
///onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,long arg3)
method = handler.getClass().getDeclaredMethod(methodName,AdapterView.class,View.class,int.class,long.class);
if(method!=null){
Object obj = method.invoke(handler, params);
return Boolean.valueOf(obj==null?false:Boolean.valueOf(obj.toString()));
}
else
throw new ViewException("no such method:"+methodName);
}catch(Exception e){
e.printStackTrace();
}
return false;
}
private static Object invokeItemSelectMethod(Object handler, String methodName, Object... params){
if(handler == null) return null;
Method method = null;
try{
///onItemSelected(AdapterView<?> arg0, View arg1, int arg2,long arg3)
method = handler.getClass().getDeclaredMethod(methodName,AdapterView.class,View.class,int.class,long.class);
if(method!=null)
return method.invoke(handler, params);
else
throw new ViewException("no such method:"+methodName);
}catch(Exception e){
e.printStackTrace();
}
return null;
}
private static Object invokeNoSelectMethod(Object handler, String methodName, Object... params){
if(handler == null) return null;
Method method = null;
try{
//onNothingSelected(AdapterView<?> arg0)
method = handler.getClass().getDeclaredMethod(methodName,AdapterView.class);
if(method!=null)
return method.invoke(handler, params);
else
throw new ViewException("no such method:"+methodName);
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}