本节是架构篇开篇 这里先解释一下最终项目的架构

目标

目标就是不需要进行一大堆的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注解框架 自己写个注解框架相关推荐

  1. 红橙Darren视频笔记 IOC注解框架 了解xUtils3与ButterKnife的原理

    1.什么是IOC IOC是Inversion of Control的缩写,直接翻译过来就叫依赖反转,看起来感觉不明觉厉,我觉得IOC就是一种解耦方式.比如原本我们在Activity中findviewb ...

  2. 红橙Darren视频笔记 Handler源码简析与handler框架模拟 ThreadLocal

    1.handler的使用 public class MainActivity extends AppCompatActivity {MyHandler myHandler;private static ...

  3. 红橙Darren视频笔记 利用阿里巴巴AndFix进行热修复

    注意 由于AndFix在2017年左右就停止更新了,在最新版本的apk上遇到很多问题,我最终也没有成功进行热修复.本节主要是学习热修复的原理 在上一篇 红橙Darren视频笔记 自己捕获异常并保存到本 ...

  4. 红橙Darren视频笔记 UML图简介

    整体架构复制自红橙原视频的课堂笔记 因为他这一课没有博客,所以没有转载链接,CSDN没有转载地址是无法作为转载类型的文章发表的,暂时标记为原创 参考链接 https://blog.csdn.net/r ...

  5. 红橙Darren视频笔记 代理模式 动态代理和静态代理

    红橙Darren视频笔记 代理模式 动态代理和静态代理(Android API 25) 关于代理模式我之前有过相关的介绍: https://blog.csdn.net/u011109881/artic ...

  6. 红橙Darren视频笔记 类加载机制(API28) 自己写个热修复 查看源码网站

    第一部分 类加载机制 一个Activity是如何被Android虚拟机找到的? 在之前的文章 红橙Darren视频笔记 自定义View总集篇(https://blog.csdn.net/u011109 ...

  7. 红橙Darren视频笔记 Behavior的工作原理源码分析

    主要coordinatorlayout的代码来自coordinatorlayout-1.0.0-sources.jar 本文从源码介绍 CoordinatorLayout 的 behavior 怎么工 ...

  8. 红橙Darren视频笔记 仿QQ侧滑效果

    这一篇没有什么新的内容 就是改写 红橙Darren视频笔记 仿酷狗侧滑效果 的侧滑的效果 1.去掉淡入淡出效果 2.加上黑色模板效果 效果: 去掉淡入淡出效果很简单 就是注释掉onScrollChan ...

  9. 红橙Darren视频笔记 ViewGroup事件分发分析 基于API27

    本节目标,通过案例,先看程序运行结果,然后跟踪源码,理解为什么会有这样的输出,继而理解view group的分发机制,感觉和证明题很像呢. 考虑以下程序的运行结果: case1: public cla ...

最新文章

  1. 如何把 XML 文件显示为 HTML 表格
  2. SCSI软件层对性能的影响
  3. FileOutPutStream in 创新实训 自然语言交流系统
  4. mysql 有十进制类型吗_MySQL数据类型
  5. android 一个很漂亮的控件ObservableScrollView(含片段代码和源码)
  6. 【Maven】Eclipse中的Maven项目安装与配置
  7. css的position属性取值
  8. 省级国土空间基础信息平台建设方案分析
  9. Linux命令之chmod命令
  10. BP神经网络python代码实现
  11. linux下连接mysql数据库命令,linux连接mysql命令
  12. IT项目画原型图工具介绍
  13. ss下,解决ncurl: (7) Failed to connect to android.googlesource.com port 443: Connection refused
  14. 关于STM32单片机延时微妙(delay_us)函数-hal库
  15. 25匹赛马得前三名问题求解
  16. 答题微信小程序实现(5):大功告成,整个模板,题库导入/切换/积分/选择对错判断/闯关成功
  17. python课程设计——当当网Python图书数据分析
  18. CI、CD、Pipeline 概念
  19. 洽谈 5G 时代“音视频”开发前景及学习方向
  20. 计算机音乐谱子 追光者,岑宁儿《追光者》简谱

热门文章

  1. c语言程序设计指针教学,C语言程序设计中指针教学要点分析
  2. tomcat下多个app 不同的图标_5G SA网络切片下,独立APP应用如何自行接入不同网络切片...
  3. 集群-如何理解集群?
  4. JavaScript get set方法 ES5/ES6写法
  5. input和textarea的区别
  6. 确保已在无线网络上启用dhcp服务器,WiFi无线网络提示未启用DHCP无法上网的解决方法教程[多图]...
  7. java算法在工作,我在北京找工作(三):java实现算法2 直接插入排序+不可变类...
  8. 明晚直播预告丨Oracle 19c X86下移经验分享
  9. 参会指南丨3分钟带你玩转2020数据技术嘉年华!
  10. 今晚直播丨如何通过APEX实现数据库自动晨检功能