您好,欢迎访问一九零五行业门户网

Java怎么使用反射和动态代理实现一个View注解绑定库

使用反射结合动态代理实现一个view注解绑定库,支持view和事件绑定,代码简洁,使用简单,扩展性强。
支持的功能@contentview 绑定layout 替代setcontentview()
@bindview 绑定view 替代findviewbyid()
@onclick 绑定点击事件 替代setonclicklistener()
@onlongclick 绑定长按事件 替代setonlongclicklistener()
代码注解类@target(elementtype.type)@retention(retentionpolicy.runtime)public @interface contentview { int value();}
@target(elementtype.field)@retention(retentionpolicy.runtime)public @interface bindview { int value();}
@target(elementtype.annotation_type)@retention(retentionpolicy.runtime)public @interface onevent { //订阅方式 string setcommonlistener(); //事件源对象 class<?> commonlistener();}
@target(elementtype.method)@retention(retentionpolicy.runtime)@onevent(setcommonlistener = "setonclicklistener", commonlistener = view.onclicklistener.class)public @interface onclick { int value();}
@target(elementtype.method)@retention(retentionpolicy.runtime)@onevent(setcommonlistener = "setonlongclicklistener", commonlistener = view.onlongclicklistener.class)public @interface onlongclick { int value();}
实现类public class msinjector { public static void inject(object object) { injectcontentview(object); injectview(object); injectevent(object); } private static void injectcontentview(object object) { class<?> clazz = object.getclass(); //获取到contentview注解 contentview contentview = clazz.getannotation(contentview.class); if (contentview == null) { return; } //获取到注解的值,也就是layoutresid int layoutresid = contentview.value(); try { //反射出setcontentview方法并调用 method method = clazz.getmethod("setcontentview", int.class); method.invoke(object, layoutresid); } catch (exception e) { e.printstacktrace(); } } private static void injectview(object object) { class<?> clazz = object.getclass(); //获取到所有字段并遍历 field[] fields = clazz.getdeclaredfields(); for (field field : fields) { field.setaccessible(true); //获取字段上的bindview注解 bindview bindview = field.getannotation(bindview.class); if (bindview == null) { continue; } //获取到viewid int viewid = bindview.value(); try { //通过反射调用findviewbyid得到view实例对象 method method = clazz.getmethod("findviewbyid", int.class); object view = method.invoke(object, viewid); //赋值给注解标注的对应字段 field.set(object, view); } catch (exception e) { e.printstacktrace(); } } } private static void injectevent(object object) { class<?> clazz = object.getclass(); //获取到当前页年所有方法并遍历 method[] declaredmethods = clazz.getdeclaredmethods(); for (method declaredmethod : declaredmethods) { declaredmethod.setaccessible(true); //获取方法上的所有注解并遍历 annotation[] annotations = declaredmethod.getdeclaredannotations(); for (annotation annotation : annotations) { //获取注解本身 class<? extends annotation> annotationtype = annotation.annotationtype(); //获取注解上的onevent注解 onevent onevent = annotationtype.getannotation(onevent.class); if (onevent == null) { continue; } //拿到注解中的元素 string setcommonlistener = onevent.setcommonlistener(); class<?> commonlistener = onevent.commonlistener(); try { //由于上边没有明确获取是哪个注解,所以这里需要使用反射获取viewid method valuemethod = annotationtype.getdeclaredmethod("value"); valuemethod.setaccessible(true); int viewid = (int) valuemethod.invoke(annotation); //通过反射findviewbyid获取到对应的view method findviewbyidmethod = clazz.getmethod("findviewbyid", int.class); object view = findviewbyidmethod.invoke(object, viewid); //通过反射获取到view中对应的setcommonlistener方法 method viewmethod = view.getclass().getmethod(setcommonlistener, commonlistener); //使用动态代理监听回调 object proxy = proxy.newproxyinstance( clazz.getclassloader(), new class[]{commonlistener}, new invocationhandler() { @override public object invoke(object proxy, method method, object[] args) throws throwable { //最终执行被标注的方法 return declaredmethod.invoke(object, null); } } ); //调用view的setcommonlistener方法 viewmethod.invoke(view, proxy); } catch (exception e) { e.printstacktrace(); } } } }}
使用@contentview(r.layout.activity_main)public class mainactivity extends appcompatactivity { @bindview(r.id.button1) private button button1; @bindview(r.id.button2) button button2; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); msinjector.inject(this); } @onclick(r.id.button1) public void clickbutton1() { toast.maketext(this, "click button1", toast.length_short).show(); } @onclick(r.id.button2) public void clickbutton2() { toast.maketext(this, "click button2", toast.length_short).show(); } @onlongclick(r.id.button1) public boolean longclickbutton1() { toast.maketext(this, "long click button1", toast.length_short).show(); return false; } @onlongclick(r.id.button2) public boolean longclickbutton2() { toast.maketext(this, "long click button2", toast.length_short).show(); return false; }}
以上就是java怎么使用反射和动态代理实现一个view注解绑定库的详细内容。
其它类似信息

推荐信息