日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入代码示例 )

發布時間:2025/6/17 Android 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入代码示例 ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 總結
  • 一、Android 事件依賴注入示例
    • 1、創建依賴注入庫
    • 2、聲明注解
      • (1)、修飾注解的注解
      • (2)、修飾方法的注解
    • 3、Activity 基類
    • 4、動態代理類調用處理程序
    • 5、依賴注入工具類
    • 6、客戶端 Activity
  • 二、博客源碼

總結

Android 依賴注入的核心就是通過反射獲取 類 / 方法 / 字段 上的注解 , 以及注解屬性 ; 在 Activity 基類中 , 獲取該注解 以及 注解屬性 , 進行相關操作 ;





一、Android 事件依賴注入示例




1、創建依賴注入庫


首先在 Android 應用中 , 創建一個 " Android Library " ,

設置主應用依賴該 Android 依賴庫 :

dependencies {implementation project(path: ':ioc_lib') }

2、聲明注解



(1)、修飾注解的注解


package kim.hsl.ioc_lib;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 自定義注解* 用于注解上的注解* 用于依賴注入視圖*/ @Target(ElementType.ANNOTATION_TYPE) // 該注解作用于注解上 @Retention(RetentionPolicy.RUNTIME) // 注解保留到運行時 public @interface EventBase {/*** 設置事件監聽的方法* @return*/String listenerSetter();/*** 設置監聽器類型* @return*/Class<?> listenerType();/*** 事件觸發后的回調方法* @return*/String callbackMethod(); }

(2)、修飾方法的注解


package kim.hsl.ioc_lib;import android.view.View;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** 自定義注解* 用于依賴注入視圖*/ @Target(ElementType.METHOD) // 該注解作用于方法上 @Retention(RetentionPolicy.RUNTIME) // 注解保留到運行時 @EventBase(listenerSetter = "setOnClickListener",listenerType = View.OnClickListener.class,callbackMethod = "onClick") public @interface OnClick {int[] value(); // 接收 int 類型數組 }

@Target(ElementType.METHOD) 表示該注解作用于方法上 ;

@Retention(RetentionPolicy.RUNTIME) 注解保留到運行時 , Java 源碼時期 RetentionPolicy.SOURCE -> Class 字節碼時期 RetentionPolicy.CLASS -> JVM 運行時時期 RetentionPolicy.RUNTIME ;

int value() 表示該注解接收一個 int 類型的值 ;


3、Activity 基類


package kim.hsl.ioc_lib;import android.app.Activity; import android.os.Bundle;import androidx.annotation.Nullable;public class BaseActivity extends Activity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 在此處注入布局// 此處傳入的 Activity 參數是 MainActivity 子類對象InjectUtils.inject(this);} }

4、動態代理類調用處理程序


package kim.hsl.ioc_lib;import android.app.Activity;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Map;public class EventInvocationHandler implements InvocationHandler {/*** 客戶端 Activity*/private Activity activity;/*** 攔截 callbackMethod 方法 , 執行 method[i] 方法* 這個 method[i] 方法就是在 MainActivity 中用戶自定義方法* 被 OnClick 注解修飾的方法* 將其封裝到 Map 集合中*/private Map<String, Method> methodMap;public EventInvocationHandler(Activity activity, Map<String, Method> methodMap) {this.activity = activity;this.methodMap = methodMap;}/*** 攔截方法 , 并使用自己的方法替換* 如 : 發現是 onClick 方法 , 則替換成用戶自定義的方法 (被 @OnClick 注解修飾的方法)* @param proxy* @param method* @param args* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 獲取回調的方法名稱, 該方法是 onClick 或者 onLongClick 或者 onTouch 等方法String name = method.getName();// 獲取對應的被調用方法Method method1 = methodMap.get(name);// 如果被調用的方法 需要被攔截 , 則能獲取到被攔截后替換的方法if (method1 != null) {// 執行用戶 Activity 中的相應方法return method1.invoke(activity, args);}// 其它方法正常執行return method.invoke(proxy, args);} }

5、依賴注入工具類


將上一篇博客 【IOC 控制反轉】Android 布局依賴注入 ( 布局依賴注入步驟 | 布局依賴注入代碼示例 ) 中的布局注入 , 抽到 injectLayout 方法中 ; 將注入視圖組件定義在 injectViews 方法中 ;

package kim.hsl.ioc_lib;import android.app.Activity; import android.icu.lang.UProperty; import android.view.View;import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map;public class InjectUtils {/*** 為 Activity 注入布局* @param activity 該 Activity 是繼承了 BaseActivity 的 MainActivity 實例對象*/public static void inject(Activity activity) {// 注入布局文件injectLayout(activity);// 注入視圖組件injectViews(activity);// 注入事件injectEvents(activity);}/*** 注入布局文件*/private static void injectLayout(Activity activity) {// 獲取 Class 字節碼對象Class<? extends Activity> clazz = activity.getClass();// 反射獲取類上的注解ContentView contentView = clazz.getAnnotation(ContentView.class);// 獲取注解中的布局 IDint layoutId = contentView.value();// 為 Activity 設置顯示的布局activity.setContentView(layoutId);}/*** 注入視圖組件*/private static void injectViews(Activity activity) {// 獲取 Class 字節碼對象Class<? extends Activity> clazz = activity.getClass();// 獲取類的屬性字段Field[] fields = clazz.getDeclaredFields();// 循環遍歷類的屬性字段for (int i = 0; i < fields.length; i ++) {// 獲取字段Field field = fields[i];// 屬性有可能是私有的, 這里設置可訪問性field.setAccessible(true);// 獲取字段上的注解, @BindView 注解// 注意不是所有的屬性字段都有 @BindView 注解BindView bindView = field.getAnnotation(BindView.class);if (bindView == null) {// 如果沒有獲取到 BindView 注解 , 執行下一次循環continue;}// 獲取注入的視圖組件int viewId = bindView.value();// 根據組件 id 獲取對應組件對象View view = activity.findViewById(viewId);try {// 通過反射設置 Activity 的對應屬性字段的值field.set(activity, view);} catch (IllegalAccessException e) {e.printStackTrace();}}}/*** 注入事件*/private static void injectEvents(Activity activity) {// 獲取 Class 字節碼對象Class<? extends Activity> clazz = activity.getClass();// 獲取所有方法Method[] methods = clazz.getDeclaredMethods();// 循環遍歷類的方法for (int i = 0; i < methods.length; i ++) {// 獲取方法的所有注解Annotation[] annotations = methods[i].getDeclaredAnnotations();// 遍歷所有的注解for (int j = 0; j < annotations.length; j ++) {// 獲取注解類型Class<? extends Annotation> annotationType = annotations[j].annotationType();// 獲取 @EventBase 注解EventBase eventBase = annotationType.getAnnotation(EventBase.class);if (eventBase == null) {// 如果沒有獲取到 EventBase 注解 , 執行下一次循環continue;}// 如果獲取到了 EventBase 注解 , 則開始獲取事件注入的三要素/*通過反射執行下面的方法textView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {}});*/// 點擊事件 View.setOnClickListenerString listenerSetter = eventBase.listenerSetter();// 監聽器類型 View.OnClickListenerClass<?> listenerType = eventBase.listenerType();// 事件觸發回調方法 public void onClick(View v)String callbackMethod = eventBase.callbackMethod();// 攔截 callbackMethod 方法 , 執行 method[i] 方法// 這個 method[i] 方法就是在 MainActivity 中用戶自定義方法// 被 OnClick 注解修飾的方法// 將其封裝到 Map 集合中Map<String, Method> methodMap = new HashMap<>();methodMap.put(callbackMethod, methods[i]);// 通過反射注入事件 , 設置組件的點擊方法// 通過反射獲取注解中的屬性// int[] value(); // 接收 int 類型數組try {// 通過反射獲取 OnClick 注解的 int[] value() 方法Method valueMethod = annotationType.getDeclaredMethod("value");// 調用 value() 方法 , 獲取視圖組件 ID 數組int[] viewIds = (int[]) valueMethod.invoke(annotations[j]);// 遍歷 ID 數組for (int k = 0; k < viewIds.length; k ++) {// 獲取組件實例對象View view = activity.findViewById(viewIds[k]);if (view == null) {continue;}// 獲取 View 視圖組件的 listenerSetter 對應方法// 這里是 View.setOnClickListener// 參數一是方法名稱 , 參數二是方法參數類型Method listenerSetterMethod =view.getClass().getMethod(listenerSetter, listenerType);// 獲取監聽器 View.OnClickListener 接口的代理對象EventInvocationHandler eventInvocationHandler =new EventInvocationHandler(activity, methodMap);Object proxy = Proxy.newProxyInstance(listenerType.getClassLoader(), // 類加載器new Class<?>[]{listenerType}, // 接口數組eventInvocationHandler); // 調用處理程序// 執行 View 的 setOnClickListener 方法, 為其設置點擊事件listenerSetterMethod.invoke(view, proxy);}} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}}} }

6、客戶端 Activity


package kim.hsl.ioc_demo;import android.util.Log; import android.view.View; import android.widget.TextView; import android.widget.Toast;import kim.hsl.ioc_lib.BaseActivity; import kim.hsl.ioc_lib.BindView; import kim.hsl.ioc_lib.ContentView; import kim.hsl.ioc_lib.OnClick;/*** 當該 MainActivity 啟動時 , 調用 BaseActivity 的 onCreate 方法* 在 BaseActivity 的 onCreate 方法中注入布局*/ @ContentView(R.layout.activity_main) // 布局注入 public class MainActivity extends BaseActivity {/*** 視圖注入*/@BindView(R.id.textView)private TextView textView;@Overrideprotected void onResume() {super.onResume();// 驗證 textView 是否注入成功Log.i("MainActivity", "textView : " + textView);}@OnClick({R.id.textView}) // 事件注入public void onClick(View view) {Toast.makeText(this, "點擊 TextView 組件", Toast.LENGTH_LONG).show();} }

運行結果 :

Logcat 打印結果 :

2021-09-22 08:25:31.759 29044-29044/kim.hsl.ioc_demo I/MainActivity: textView : android.widget.TextView{a988249 VFED..C.. ........ 440,840-640,891 #7f08017e app:id/textView}





二、博客源碼



GitHub : https://github.com/han1202012/IOC_Demo

CSDN : https://download.csdn.net/download/han1202012/24031128

總結

以上是生活随笔為你收集整理的【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入代码示例 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩成人高清在线 | 在线观看福利片 | 30一40一50老女人毛片 | 日韩不卡av | 中文字幕一区二区视频 | 韩日一区二区三区 | 丰满少妇被猛烈进入高清播放 | 中文字幕一区二区三区在线不卡 | 久久中文网 | 久草久| 三级黄色网络 | 亚洲免费精品视频在线观看 | 91国产免费观看 | 午夜伦理在线观看 | 国产亚洲女人久久久久毛片 | 成人a在线| 国产又黄又粗又硬 | av影片在线| 黄色片免费 | 捆绑调教在线观看 | 噜噜av| 超碰凹凸 | 国产成人精品aa毛片 | 国产h视频在线观看 | 国产第113页 | 亚洲视频一区在线观看 | 久久九九色 | 亚洲精品一区二区三区婷婷月 | 成人精品av | 性视频免费看 | 亚洲一卡二卡在线观看 | 欧美黄色免费视频 | 亚洲一区二区三区三州 | 日韩欧美在线免费 | 久久精精品久久久久噜噜 | 女儿的朋友5中汉字晋通话 欧美成人免费高清视频 | 香蕉久久精品 | 国产免费黄色网址 | 亚洲欧美国产一区二区 | 日本视频网站在线观看 | 葵司免费一区二区三区四区五区 | 日韩一中文字幕 | av片免费在线| 欧洲午夜精品 | 国产精品电影一区 | 狠狠干网 | 国产乱淫av片 | h无码动漫在线观看 | 国产av成人一区二区三区高清 | 国产精品视频在线观看 | 成人免费黄色片 | 蜜桃啪啪 | 少妇搡bbbb搡bbb搡小说 | www.色呦呦 | 国产人妻精品一区二区三区 | 九九免费在线视频 | 免费手机av| h片在线观看视频 | 欧美岛国国产 | 黄网av| 精品人妻aV中文字幕乱码色欲 | 在线免费看污视频 | 日韩一二三四 | 久久精品视频1 | 中国丰满老妇xxxxx交性 | 一级黄色免费视频 | 日韩精品视频播放 | 老司机精品福利视频 | 日本欧美国产在线 | 美女视频91| 在线日韩三级 | 波多野结衣有码 | 成人av福利 | 国产污污 | 婷婷人体 | 日韩在线视频一区二区三区 | 国产aaaaaa| 美女操出白浆 | 色屋在线 | 亚洲精品国产精品乱码桃花 | 人妻内射一区二区在线视频 | 亚洲免费精品视频 | 国产精品一级片在线观看 | eeuss一区二区三区 | 嫩草国产在线 | 日本黄色大片免费看 | 波多野结衣电车痴汉 | 亚洲成熟少妇视频在线观看 | 狠狠伊人 | 免费观看黄网站 | 日日夜夜影院 | 日日骚av | 欧美大片一区二区三区 | 国产精品va在线观看无码 | 青青青草国产 | 国产精品美女久久久免费 | av观看网址 | 久草网在线| 国产成人在线精品 |