美文网首页
IOC实现ButterKnife处理安卓23种事件

IOC实现ButterKnife处理安卓23种事件

作者: 飞马_6886 | 来源:发表于2020-05-06 12:09 被阅读0次

    前言

    虽然butterknife正慢慢被淘汰,被DataBing所代替是大势所趋,但是显然它已经完成了它的使命。想当年还是红极一时,项目使用率还是挺高的。今天我们就模仿实现它的事件处理效果。要实现这个效果,用到的知识点还是蛮多的,比如注解,反射,动态代理等等。下面我会结合代码来讲解他的实现过程

    首先定义一个元注解,用来设置事件的三要素

    三要素包括
    1.要设置什么类型的事件,比如setOnClickListener,setOnLongClickListener等十多种类型
    2.事件类型,一般是接口,举例说明比如:View.OnClickListenr,View.OnLongClickListener等等。
    3.要执行的回调方法,就是接口里定义的方法。比如 onClick,onLongClick等。

    //事件的三要素
    @Target(ElementType.ANNOTATION_TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface EventBase {
        String listenerSetter();
        Class<?> listenerType();
        String callbackMethod();
    }
    

    定义事件类型的注解

    为了方便扩展,每种事件定义一个注解,并且加上对应的元注解,为了方便这里只定义了两种类型的事件,如果想要其他类型的事件可以新增定义进行扩展。

    这里要注意:listenerSetter 参数拼写字符串时一定不能拼错,因为掉进过这个坑里。

    普通点击事件的注解
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @EventBase(listenerSetter = "setOnClickListener",listenerType = View.OnClickListener.class,callbackMethod = "onClick")
    public @interface OnClick {
        @IdRes int[] value();
    }
    
    
    长按事件的注解
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @EventBase(listenerSetter = "setOnLongClickListener",
    listenerType = View.OnLongClickListener.class,
    callbackMethod = "onLongClick")
    public @interface LongClick {
        @IdRes int[] value();
    }
    

    下面就是功能实现的核心代码

    实现的过程中主要是要细心,想明白之间的关系,要正确传参。

    public class InjectUtil {
        private static String TAG = InjectUtil.class.getSimpleName();
    
        public static void inject(final Activity activity){
            Class<? extends Activity> cls = activity.getClass();
            Method[] methods = cls.getDeclaredMethods();
            for (final Method method : methods){
                Annotation[] annotations = method.getAnnotations();
                for (Annotation annotation : annotations){
                    //获取注解类
                    Class<?> annotationType = annotation.annotationType();
                    EventBase  eventBase = annotationType.getAnnotation(EventBase.class);
                    if (eventBase == null){
                        continue;
                    }
                    String listenerSetter = eventBase.listenerSetter();
                    Class<?> listenerType = eventBase.listenerType();
                    String callback = eventBase.callbackMethod();
    
                    Method valueMethod = null;
                    try {
                        valueMethod = annotationType.getDeclaredMethod("value");
                        int[] resIDs = (int[]) valueMethod.invoke(annotation);
                        for(int viewId:resIDs){
                            Method findViewByIdMethod = cls.getMethod("findViewById", int.class);
                            View view = (View) findViewByIdMethod.invoke(activity,viewId);
    
                            Object proxy = Proxy.newProxyInstance(listenerType.getClassLoader(),
                                    new Class[]{listenerType}, new InvocationHandler() {
                                        @Override
                                        public Object invoke(Object proxy, Method method1, Object[] args) throws Throwable {
                                            return method.invoke(activity,args);
                                        }
                                    });
                            Method setMethod = view.getClass().getMethod(listenerSetter,listenerType);
                            setMethod.invoke(view,proxy);
                        }
    
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
    
    
                }
    
            }
        }
    }
    

    最后贴出调用代码

    public class MainActivity extends AppCompatActivity  {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            InjectUtil.inject(this);
        }
    
        @OnClick({R.id.btn_two,R.id.my_btn_one})
        public void myClick(View view){
            System.out.println("click执行了");
            Toast.makeText(this,"点击了。。。",Toast.LENGTH_SHORT).show();
        }
    
    
        @LongClick({R.id.btn_three})
        public boolean myLongClick(View view){
            Toast.makeText(this,"长按了---",Toast.LENGTH_SHORT).show();
            return false;
        }
    
    }
    

    结语:

    如果能想明白各个对象之间的关系,就不难实现这个功能了。最后,欢迎大家多多指正。

    相关文章

      网友评论

          本文标题:IOC实现ButterKnife处理安卓23种事件

          本文链接:https://www.haomeiwen.com/subject/aomightx.html