Android之旅

动手撸一个ButterKnife

2017-12-02  本文已影响49人  h2coder

解决方法

public interface ViewInjector {
    /**
     * 以Activity为注入对象
     *
     * @param activity Activity实例
     */
    void inject(Activity activity);
}
@Target(ElementType.FIELD)//设置注解使用范围为变量
@Retention(RetentionPolicy.RUNTIME)//设置注解生命时长,运行时
public @interface ViewInject {
    /**
     * View value
     */
    int value();
}
public class ViewInjectorImpl implements ViewInjector {
    private ViewInjectorImpl() {
    }

    private static final class SingletonHolder {
        private static final ViewInjectorImpl instance = new ViewInjectorImpl();
    }

    public static ViewInjectorImpl getInstance() {
        return SingletonHolder.instance;
    }

    @Override
    public void inject(Activity activity) {
        if (activity == null) {
            return;
        }
        //绑定控件
        bindViewId(activity);
    }
}

    /**
     * 绑定View的Id
     */
    private void bindViewId(Activity activity) {
        try {
            //1.获取所有的成员变量
            Class<? extends Activity> clazz = activity.getClass();
            //2.遍历所有成员变量,找到使用了ViewInject注解的成员变量(所有类型,包括private)
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                //设置允许访问
                field.setAccessible(true);
                ViewInject annotation = field.getAnnotation(ViewInject.class);
                if (annotation != null) {
                    //3.将使用了注解的成员变量上标记的id值取出
                    int id = annotation.value();
                    //4.调用activity的findViewById查找控件
                    if (id > 0) {
                        View view = activity.findViewById(id);
                        //5.将控件设置给成员变量
                        field.set(activity, view);
                    } else {
                        throw new RuntimeException("ViewInject annotation must have view value");
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
public class ViewInjectManager {

    /**
     * 获取注入器实现对象
     *
     * @return 注入器实例
     */
    public static ViewInjector getOperate() {
        return ViewInjectorImpl.getInstance();
    }
}
@ViewInject(R.id.startBtn)
    public Button startBtn;
    
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewInjectorImpl.getInstance().inject(this);
        //如果注入成功,Button的文字就会变为“bind success”
        toastBtn.setText("bind success");
    }

添加OnClick、OnLongClick使用

//点击事件注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClick {
    int[] value();
}

//长按事件注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnLongClick {
    int[] value();
}
/**
     * 绑定View的OnClick事件
     *
     * @param activity
     */
    private void bindViewEvent(final Activity activity) {
        //1.获取所有的方法
        Class<? extends Activity> clazz = activity.getClass();
        //2.遍历所有的方法
        Method[] methods = clazz.getDeclaredMethods();
        //3.获取标记了OnClick注解的方法
        for (final Method method : methods) {
            OnClick onClickAnnotation = method.getAnnotation(OnClick.class);
            if (onClickAnnotation != null) {
                //4.取出id,查找View
                int id = onClickAnnotation.value();
                View view = activity.findViewById(id);
                //5.给View绑定onClick,点击时执行
                view.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        try {
                            Class<?>[] parameterTypes = method.getParameterTypes();
                            int paramsCount = parameterTypes.length;
                            if (paramsCount == 0) {
                                method.invoke(activity, new Object[]{});
                            } else {
                                method.invoke(activity, v);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
            //长按事件
            OnLongClick onLongAnnotation = method.getAnnotation(OnLongClick.class);
            if (onLongAnnotation != null) {
                int id = onLongAnnotation.value();
                View view = activity.findViewById(id);
                if (view != null) {
                    view.setOnLongClickListener(new View.OnLongClickListener() {
                        @Override
                        public boolean onLongClick(View v) {
                            try {
                                Class<?>[] parameterTypes = method.getParameterTypes();
                                int paramsCount = parameterTypes.length;
                                Object o;
                                if (paramsCount == 0) {
                                    o = method.invoke(activity, new Object[]{});
                                } else {
                                    o = method.invoke(activity, new Object[]{v});
                                }
                                return (boolean) o;
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            return false;
                        }
                    });
                }
            }
        }
    }
@OnClick(R.id.toastBtn)
    public void OnClick(View view) {
        switch (view.getId()) {
            case R.id.toastBtn:
                toast("onClick !!!");
                break;
        }
    }

    @OnLongClick(R.id.toastBtn)
    public boolean onLongClick(View view) {
        toast("onLongClick !!!");
        return true;
    }

    private void toast(String msg) {
        Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
    }

改进

结语

上一篇下一篇

猜你喜欢

热点阅读