红橙Darren视频笔记 IOC注解框架 自己写个注解框架
本节是架构篇开篇 这里先解释一下最终项目的架构
目标
目标就是不需要进行一大堆的findviewbyid以及各种setListener的杂乱代码,本文以findviewbyid和setOnClickListener为例 介绍如何进行属性绑定和事件绑定
开始实现
1.创建测试module
public class ActivityIocTest extends AppCompatActivity {@ViewById(R.id.tv)TextView mTextView;@ViewById(R.id.btn)Button mButton;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_ioc_test);ViewUtils.injectActivity(this);mTextView.setText("Tv text!!!!");mButton.setText("Button text!!!!");}@OnClick({R.id.tv,R.id.btn})public void onItemClick(View view){switch (view.getId()){case R.id.tv:Toast.makeText(this,"text view clicked",Toast.LENGTH_SHORT).show();break;case R.id.btn:Toast.makeText(this,"button clicked",Toast.LENGTH_SHORT).show();break;}}
}<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Ioc Test" /><Buttonandroid:id="@+id/btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Ioc Test" /></LinearLayout>
2.创建ioc module 专门生成注解,进行属性和事件绑定
3.测试module依赖ioc模块
dependencies {...implementation project(path: ':ioc')//添加ioc模块注解依赖
}
4.编写ioc模块
4.1 注解的声明
/*** Created by hjcai on 2021/2/7.*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClick {//可以传入多个参数int[] value();
}
/*** Created by hjcai on 2021/2/5.* 注解声明*/@Target(ElementType.FIELD)//该注解表示只能用于类的属性
//其他常见属性如 TYPE用在类上 CONSTRUCTOR用在构造函数上 METHOD用于方法
@Retention(RetentionPolicy.RUNTIME)
public//该注解表示在运行时生效
//其他常见属性如 CLASS编译时 RUNTIME运行时 SOURCE源码级别@interface ViewById {//value代表可以该注解可以添加一个参数int value();
}
4.2 工具类编写
/*** Created by hjcai on 2021/2/5.* <p>* 主要是调用findViewById*/
class ViewFinder {private Activity mActivity;public ViewFinder(Activity activity) {this.mActivity = activity;}public View findViewById(int viewId) {return mActivity.findViewById(viewId);}
}
4.3 实际注入属性与方法的类
/*** Created by hjcai on 2021/2/5.*/
public class ViewUtils {//Activity绑定public static void injectActivity(Activity activity) {injectActivity(new ViewFinder(activity), activity);}private static void injectActivity(ViewFinder finder, Object object) {injectActivityField(finder, object);injectActivityEvent(finder, object);}//注入属性private static void injectActivityField(ViewFinder finder, Object object) {//1 反射 获取class里面所有属性Class<?> clazz = object.getClass();Field[] fields = clazz.getDeclaredFields();//获取Activity的所有属性包括私有和共有for (Field field : fields) {//2 遍历fields 找到添加了注解ViewById的filedViewById viewById = field.getAnnotation(ViewById.class);if (viewById != null) {//3 获取注解里面的id值int viewId = viewById.value();View view = finder.findViewById(viewId);//相当于调用Activity.findViewByIdif (view != null) {field.setAccessible(true);try {//4 动态的注入找到的Viewfield.set(object, view);//利用反射 将object(activity)中的声明了ViewById注解的地方 替换成刚刚find的view} catch (IllegalAccessException e) {e.printStackTrace();}}}}}private static void injectActivityEvent(ViewFinder finder, Object object) {//1 反射 获取class里面所有属性Class<?> clazz = object.getClass();Method[] methods = clazz.getDeclaredMethods();//获取Activity的所有方法包括私有和共有for (Method method : methods) {//2 遍历fields 找到添加了注解OnClick的methodOnClick onClick = method.getAnnotation(OnClick.class);if (onClick != null) {//3 获取注解里面的id值int[] viewIds = onClick.value();for (int viewId : viewIds) {View view = finder.findViewById(viewId);//相当于调用Activity.findViewByIdif (view != null) {// 4. 给每个view设置点击事件view.setOnClickListener(new DeclaredOnClickListener(method, object));}}}}}private static class DeclaredOnClickListener implements View.OnClickListener {private Object mObject;private Method mMethod;//实际定义的方法 在这里是 ActivityIocTest.onItemClickpublic DeclaredOnClickListener(Method method, Object object) {this.mObject = object;this.mMethod = method;}@Overridepublic void onClick(View v) {try {// 所有方法都可以 包括私有共有mMethod.setAccessible(true);// 反射执行方法// 当View被点击时执行mMethod.invoke(mObject, v);//通过反射 调用mObject的声明了onClick注解了的方法 参数为v} catch (Exception e) {e.printStackTrace();try {mMethod.invoke(mObject, null);} catch (Exception e1) {e1.printStackTrace();}}}}
}
小结
这里的原理和xUtil3里面的ioc注解原理一样都是利用annotation+反射实现的
红橙Darren视频笔记 IOC注解框架 自己写个注解框架相关推荐
- 红橙Darren视频笔记 IOC注解框架 了解xUtils3与ButterKnife的原理
1.什么是IOC IOC是Inversion of Control的缩写,直接翻译过来就叫依赖反转,看起来感觉不明觉厉,我觉得IOC就是一种解耦方式.比如原本我们在Activity中findviewb ...
- 红橙Darren视频笔记 Handler源码简析与handler框架模拟 ThreadLocal
1.handler的使用 public class MainActivity extends AppCompatActivity {MyHandler myHandler;private static ...
- 红橙Darren视频笔记 利用阿里巴巴AndFix进行热修复
注意 由于AndFix在2017年左右就停止更新了,在最新版本的apk上遇到很多问题,我最终也没有成功进行热修复.本节主要是学习热修复的原理 在上一篇 红橙Darren视频笔记 自己捕获异常并保存到本 ...
- 红橙Darren视频笔记 UML图简介
整体架构复制自红橙原视频的课堂笔记 因为他这一课没有博客,所以没有转载链接,CSDN没有转载地址是无法作为转载类型的文章发表的,暂时标记为原创 参考链接 https://blog.csdn.net/r ...
- 红橙Darren视频笔记 代理模式 动态代理和静态代理
红橙Darren视频笔记 代理模式 动态代理和静态代理(Android API 25) 关于代理模式我之前有过相关的介绍: https://blog.csdn.net/u011109881/artic ...
- 红橙Darren视频笔记 类加载机制(API28) 自己写个热修复 查看源码网站
第一部分 类加载机制 一个Activity是如何被Android虚拟机找到的? 在之前的文章 红橙Darren视频笔记 自定义View总集篇(https://blog.csdn.net/u011109 ...
- 红橙Darren视频笔记 Behavior的工作原理源码分析
主要coordinatorlayout的代码来自coordinatorlayout-1.0.0-sources.jar 本文从源码介绍 CoordinatorLayout 的 behavior 怎么工 ...
- 红橙Darren视频笔记 仿QQ侧滑效果
这一篇没有什么新的内容 就是改写 红橙Darren视频笔记 仿酷狗侧滑效果 的侧滑的效果 1.去掉淡入淡出效果 2.加上黑色模板效果 效果: 去掉淡入淡出效果很简单 就是注释掉onScrollChan ...
- 红橙Darren视频笔记 ViewGroup事件分发分析 基于API27
本节目标,通过案例,先看程序运行结果,然后跟踪源码,理解为什么会有这样的输出,继而理解view group的分发机制,感觉和证明题很像呢. 考虑以下程序的运行结果: case1: public cla ...
最新文章
- 如何把 XML 文件显示为 HTML 表格
- SCSI软件层对性能的影响
- FileOutPutStream in 创新实训 自然语言交流系统
- mysql 有十进制类型吗_MySQL数据类型
- android 一个很漂亮的控件ObservableScrollView(含片段代码和源码)
- 【Maven】Eclipse中的Maven项目安装与配置
- css的position属性取值
- 省级国土空间基础信息平台建设方案分析
- Linux命令之chmod命令
- BP神经网络python代码实现
- linux下连接mysql数据库命令,linux连接mysql命令
- IT项目画原型图工具介绍
- ss下,解决ncurl: (7) Failed to connect to android.googlesource.com port 443: Connection refused
- 关于STM32单片机延时微妙(delay_us)函数-hal库
- 25匹赛马得前三名问题求解
- 答题微信小程序实现(5):大功告成,整个模板,题库导入/切换/积分/选择对错判断/闯关成功
- python课程设计——当当网Python图书数据分析
- CI、CD、Pipeline 概念
- 洽谈 5G 时代“音视频”开发前景及学习方向
- 计算机音乐谱子 追光者,岑宁儿《追光者》简谱
热门文章
- c语言程序设计指针教学,C语言程序设计中指针教学要点分析
- tomcat下多个app 不同的图标_5G SA网络切片下,独立APP应用如何自行接入不同网络切片...
- 集群-如何理解集群?
- JavaScript get set方法 ES5/ES6写法
- input和textarea的区别
- 确保已在无线网络上启用dhcp服务器,WiFi无线网络提示未启用DHCP无法上网的解决方法教程[多图]...
- java算法在工作,我在北京找工作(三):java实现算法2 直接插入排序+不可变类...
- 明晚直播预告丨Oracle 19c X86下移经验分享
- 参会指南丨3分钟带你玩转2020数据技术嘉年华!
- 今晚直播丨如何通过APEX实现数据库自动晨检功能