日韩性视频-久久久蜜桃-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 事件依赖注入 ( 事件依赖注入代码示例 )的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国产高清一区在线观看 | 5d肉蒲团之性战奶水 | 亚洲黄网站在线观看 | 成人高潮片免费 | 黄a毛片 | 国产最新在线 | 青青操影院 | 亚洲一区视频网站 | 成人少妇影院yyyy | 毛片国产精品 | 99在线视频精品 | 亚洲va韩国va欧美va | av日韩一区二区 | 国产视频www| 婷婷成人综合 | 中文在线观看免费视频 | 黄色的网站免费看 | av成人免费| 先锋资源国产 | 亚洲小视频在线播放 | 曰本无码人妻丰满熟妇啪啪 | 欧美日韩精选 | 天天操天天射天天 | 91福利视频在线 | 最新国产露脸在线观看 | 欧美顶级metart裸体全部自慰 | 国产理论片在线观看 | 久久精品九九 | 久久有精品| 日韩黄色在线视频 | 青青在线观看视频 | www.成人国产 | 精品99久久久 | 精品人伦一区二区三区蜜桃免费 | 久久小视频 | 国产精品女人久久久 | www.我爱av| 亚洲在线视频播放 | 男人的天堂网av | 懂色av蜜臀av粉嫩av喷吹 | 少妇精品久久久久www | 欧美一区永久视频免费观看 | 成人人人人人欧美片做爰 | 国产乱码在线 | 国产视频91在线 | 91精品国产福利在线观看 | 五月婷婷激情四射 | 久久久久久久网 | 熟妇女人妻丰满少妇中文字幕 | 在线观看国产免费视频 | 久久精品片| 久久久久久久久久久久 | 美女网站免费观看视频 | 欧美日韩国产一区 | 黄色a级免费 | 日本一区精品视频 | 久久av免费观看 | 日韩在线观看一区二区 | 午夜国产福利 | 性欧美hd调教 | 九九综合九九综合 | 黄色一区二区三区 | 日韩一区二区在线播放 | 伊人午夜 | 毛片少妇| 综合亚洲视频 | 亚洲第5页 | 又黄又爽网站 | 久久国产一区二区 | 亚洲欧美日韩成人 | 日免费视频| 不用播放器的av网站 | 精品97人妻无码中文永久在线 | 亚洲综合精品 | 欧美区二区三区 | 亚洲国产精品久久久久 | 91av导航 | 12av在线| 精品国产乱码久久久久久久软件 | 丰满人妻一区二区三区53 | av先锋在线 | 国产sm在线观看 | 波多野结衣黄色片 | 北条麻妃在线一区二区 | 521a人成v香蕉网站 | 狠狠干狠狠操视频 | 国产模特av私拍大尺度 | 日本精品黄| 在线视频三区 | 综合成人 | 成人女同在线观看 | 欧美一区二区成人 | 天天操一操 | 美女视频黄色 | 都市激情一区 | 少妇愉情理伦片bd | 欧美aaa一级片 | 99蜜桃臀久久久欧美精品网站 | 日韩看片 |