您好,登錄后才能下訂單哦!
本篇內容介紹了“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注解綁定庫”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。