写在前面 打造自己的简单IOC注解框架
1.创建annotation类 View 1 2 3 4 5 6 7 //代表Annotation的位置, FIELD属性 TYPE类上 CONSTRUCTOR构造函数上 @Target(ElementType.FIELD) //代表什么时候生效 CLASS编译时 RUNTIME运行时 SOURCE源码时 @Retention(RetentionPolicy.RUNTIME) public @interface ViewById { int value(); }
点击监听 1 2 3 4 5 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface OnClick { int[] value(); }
网络状态判断 1 2 3 4 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface CheckNet { }
2.创建View的findViewById的辅助类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class ViewFinder { private Activity mActivity; private View mView; public ViewFinder(Activity activity) { this.mActivity = activity; } public ViewFinder(View view) { this.mView = view; } public View findViewById(int viewId) { return mActivity != null ? mActivity.findViewById(viewId) : mView.findViewById(viewId); } }
3.创建工具类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 public class ViewUtils { public static void inject(Activity activity) { inject(new ViewFinder(activity), activity); } public static void inject(View view) { inject(new ViewFinder(view), view); } public static void inject(View view, Object object) { inject(new ViewFinder(view), object); } //兼容 上面三个方法,object -> 反射需要执行的类 private static void inject(ViewFinder finder, Object object) { injectField(finder, object); injectEvent(finder, object); } // 注入属性 private static void injectField(ViewFinder finder, Object object) { //1.获取类里面的所有属性 Class<?> clazz = object.getClass(); // 获取所有属性包括私有和共有 Field[] fields = clazz.getDeclaredFields(); //2.获取ViewById找到view for (Field field : fields) { ViewById viewById = field.getAnnotation(ViewById.class); if (viewById != null) { //获取注解里的id值->R.id.xx int viewId = viewById.value(); //3.findViewById找到view View view = finder.findViewById(viewId); if (view != null) { //能够注入所有修饰符private public field.setAccessible(true); try { //4.动态注入扎到view field.set(object, view); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } } private static void injectEvent(ViewFinder finder, Object object) { Class<?> clazz = object.getClass(); Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { OnClick onClick = method.getAnnotation(OnClick.class); if (onClick != null) { int[] viewIds = onClick.value(); for (int viewId : viewIds) { View view = finder.findViewById(viewId); boolean isCheckNet = method.getAnnotation(CheckNet.class) != null; if (view != null) { view.setOnClickListener(new DeclaredOnClickListener(method, object, isCheckNet)); } } } } } private static class DeclaredOnClickListener implements View.OnClickListener { private final Object mObject; private final Method mMethod; private final boolean mIsCheckNet; public DeclaredOnClickListener(Method method, Object object, boolean isCheckNet) { this.mMethod = method; this.mObject = object; this.mIsCheckNet = isCheckNet; } @Override public void onClick(View v) { if (mIsCheckNet) { if (!networkAvailable(v.getContext())) { Toast.makeText(v.getContext(), "网络不可用", Toast.LENGTH_SHORT).show(); return; } } try { mMethod.setAccessible(true); mMethod.invoke(mObject, v); } catch (Exception e) { e.printStackTrace(); try { mMethod.setAccessible(true); mMethod.invoke(mObject, null); } catch (Exception e1) { e1.printStackTrace(); } } } } private static boolean networkAvailable(Context context) { try { ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetWorkInfo = connectivityManager.getActiveNetworkInfo(); if (activeNetWorkInfo != null && activeNetWorkInfo.isConnected()) { return true; } } catch (Exception e) { e.printStackTrace(); } return false; } }
使用方法 1 2 3 4 5 6 7 8 9 @ViewById(R.id.test_tv) private TextView textView; @CheckNet @OnClick(R.id.test_tv) private void onClick(View view) { Toast.makeText(this, "click", Toast.LENGTH_SHORT).show(); }