日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )

發(fā)布時(shí)間:2025/6/17 41 豆豆

文章目錄

  • 前言
  • 一、創(chuàng)建 事件監(jiān)聽器 對(duì)應(yīng)的 動(dòng)態(tài)代理
  • 二、動(dòng)態(tài)代理 數(shù)據(jù)準(zhǔn)備
  • 三、動(dòng)態(tài)代理 調(diào)用處理程序
  • 四、動(dòng)態(tài)代理 實(shí)例對(duì)象創(chuàng)建

前言

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

在博客 【IOC 控制反轉(zhuǎn)】Android 事件依賴注入 ( 事件三要素 | 修飾注解的注解 | 事件依賴注入步驟 ) 中 , 定義了 222 個(gè)注解 ,

  • 第一個(gè)是方法上的注解 , 用于修飾方法 ;
  • 第二個(gè)是修飾注解的注解 , 該注解用于配置注入的方法 ( 事件監(jiān)聽方法 | 監(jiān)聽器類型 | 監(jiān)聽器回調(diào)方法 ) ;

事件依賴注入比較復(fù)雜 , 涉及到動(dòng)態(tài)代理 , 本博客分析 【IOC 控制反轉(zhuǎn)】Android 事件依賴注入 ( 事件依賴注入代碼示例 ) 事件依賴注入的詳細(xì)步驟 ;


本博客的核心是 : 使用動(dòng)態(tài)代理 , 創(chuàng)建 View.OnClickListener 或 View.OnLongClickListener 或 View.onTouchListener 等接口的動(dòng)態(tài)代理類 ;
攔截相應(yīng)的 onClick , onLongClick , onTouch 方法 , 執(zhí)行自己的方法 , 其它方法正常執(zhí)行 ;





一、創(chuàng)建 事件監(jiān)聽器 對(duì)應(yīng)的 動(dòng)態(tài)代理



為組件設(shè)置的監(jiān)聽器可能是 View.OnClickListener 或 View.OnLongClickListener 或 View.onTouchListener 等監(jiān)聽器 , 因此使用 靜態(tài)代理 , 需要為每個(gè)監(jiān)聽器都要設(shè)置一個(gè)單獨(dú)的類 , 比較繁瑣 ;

這里使用動(dòng)態(tài)代理實(shí)現(xiàn)上述功能 ;

動(dòng)態(tài)代理是作用于接口上的 , 根據(jù)接口動(dòng)態(tài)創(chuàng)建該接口子類的代理對(duì)象 ;

原來(lái)是設(shè)置了一個(gè)匿名內(nèi)部類 , 這個(gè)匿名內(nèi)部類就是代理模式中的 被代理對(duì)象 ;

textView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {}});

現(xiàn)在使用 動(dòng)態(tài)代理 , 創(chuàng)建一個(gè) 代理對(duì)象 , 代理 上述 匿名內(nèi)部類 被代理對(duì)象 , 要在調(diào)用 onClick 方法時(shí) , 注入自己的業(yè)務(wù)邏輯 ;


該動(dòng)態(tài)代理中的元素梳理 :

  • 目標(biāo)對(duì)象 ( 主題對(duì)象 ) : View.OnClickListener 接口 ;
  • 被代理對(duì)象 : View.OnClickListener 接口匿名內(nèi)部類 ;
new View.OnClickListener() {@Overridepublic void onClick(View v) {}}
  • 代理對(duì)象 : 使用 Proxy.newProxyInstance 方法 , 由 JVM 自動(dòng)生成字節(jié)碼類 就是代理對(duì)象 , 之后返回一個(gè)代理對(duì)象 的實(shí)例對(duì)象 ;
  • 客戶端 : 框架開發(fā)者開發(fā)的 依賴注入 工具類 , 在該工具類中執(zhí)行動(dòng)態(tài)代理的調(diào)用操作 ;




二、動(dòng)態(tài)代理 數(shù)據(jù)準(zhǔn)備



執(zhí)行動(dòng)態(tài)代理前 , 首先要知道攔截接口方法 , 以及要注入的方法 ;

攔截到接口方法后 , 替換成自己注入的方法 , 就是調(diào)用自己的方法 ;

將二者封裝到 Map 集合中 , 方便在攔截后 , 調(diào)用 Map 的 get 方法 , 查看是否有要注入的方法 ;

// 攔截 callbackMethod 方法 , 執(zhí)行 method[i] 方法// 這個(gè) method[i] 方法就是在 MainActivity 中用戶自定義方法// 被 OnClick 注解修飾的方法// 將其封裝到 Map 集合中Map<String, Method> methodMap = new HashMap<>();methodMap.put(callbackMethod, methods[i]);



三、動(dòng)態(tài)代理 調(diào)用處理程序



在該動(dòng)態(tài)代理中 , 首先要注入 Activity 和 上面準(zhǔn)備的 Map 集合 , Map 集合中封裝了 要攔截的接口方法 和 要注入的方法 ;


首先獲取被代理接口中的 回調(diào)的方法名稱, 該方法是 onClick 或者 onLongClick 或者 onTouch 等方法 ;

Method 方法在參數(shù)中有 , 直接調(diào)用 Method method 參數(shù)的 getName() 方法獲取接口名稱 ;

// 獲取回調(diào)的方法名稱, 該方法是 onClick 或者 onLongClick 或者 onTouch 等方法String name = method.getName();

然后到 Map 集合中查找 , 是否要攔截該 接口方法 , 如果要攔截 , 肯定能從 Map 集合中獲取到要注入的方法 , 如果不需要攔截 , 獲取的結(jié)果是 null ;

// 獲取對(duì)應(yīng)的被調(diào)用方法Method method1 = methodMap.get(name);

如果被調(diào)用的方法 需要被攔截 , 則能獲取到被攔截后替換的方法 , 執(zhí)行該注入的方法即可 ;

// 如果被調(diào)用的方法 需要被攔截 , 則能獲取到被攔截后替換的方法if (method1 != null) {// 執(zhí)行用戶 Activity 中的相應(yīng)方法return method1.invoke(activity, args);}

如果不攔截該方法 , 則獲取的注入方法為 null , 直接返回該方法 , 注意調(diào)用 method.invoke(proxy, args) , 正常執(zhí)行該接口方法即可 ;

// 其它方法正常執(zhí)行return method.invoke(proxy, args);

代碼示例 :

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 方法 , 執(zhí)行 method[i] 方法* 這個(gè) method[i] 方法就是在 MainActivity 中用戶自定義方法* 被 OnClick 注解修飾的方法* 將其封裝到 Map 集合中*/private Map<String, Method> methodMap;public EventInvocationHandler(Activity activity, Map<String, Method> methodMap) {this.activity = activity;this.methodMap = methodMap;}/*** 攔截方法 , 并使用自己的方法替換* 如 : 發(fā)現(xiàn)是 onClick 方法 , 則替換成用戶自定義的方法 (被 @OnClick 注解修飾的方法)* @param proxy* @param method* @param args* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 獲取回調(diào)的方法名稱, 該方法是 onClick 或者 onLongClick 或者 onTouch 等方法String name = method.getName();// 獲取對(duì)應(yīng)的被調(diào)用方法Method method1 = methodMap.get(name);// 如果被調(diào)用的方法 需要被攔截 , 則能獲取到被攔截后替換的方法if (method1 != null) {// 執(zhí)行用戶 Activity 中的相應(yīng)方法return method1.invoke(activity, args);}// 其它方法正常執(zhí)行return method.invoke(proxy, args);} }



四、動(dòng)態(tài)代理 實(shí)例對(duì)象創(chuàng)建



調(diào)用 Proxy.newProxyInstance 方法 , 創(chuàng)建動(dòng)態(tài)代理的 實(shí)例對(duì)象 , 傳入到代理的接口數(shù)組 , 這個(gè)接口數(shù)組元素可以是 View.OnClickListener.class 或 View.OnLongClickListener.class 或 View.OnTouchListener.class 等字節(jié)碼類 ;

在調(diào)用處理程序中 , 攔截上述接口中的方法 , 并替換成自己的方法 , 也就是用戶在 MainActivity 中使用 @OnClick 注解修飾的方法 ;

// 獲取監(jiān)聽器 View.OnClickListener 接口的代理對(duì)象EventInvocationHandler eventInvocationHandler =new EventInvocationHandler(activity, methodMap);Object proxy = Proxy.newProxyInstance(listenerType.getClassLoader(), // 類加載器new Class<?>[]{listenerType}, // 接口數(shù)組eventInvocationHandler); // 調(diào)用處理程序

該動(dòng)態(tài)代理實(shí)例對(duì)象創(chuàng)建后 , 將其當(dāng)做 View.OnClickListener.class 或 View.OnLongClickListener.class 或 View.OnTouchListener.class 等字節(jié)碼類的實(shí)例對(duì)象使用即可 ;

總結(jié)

以上是生活随笔為你收集整理的【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。