自定义Android注解Part3:绑定
上一节我们已经将自动生成注解代码部分介绍完毕,今天这篇文章是自定义Android注解系列的最后一篇文章。希望大家这一路走来有所收获。
经过前面的了解,我们三大部分:butterknife-annotations、butterknife-compiler与butterknife-bind。现在就剩下最后一部分butterknife-bind。该部分是对我们前面定义的注解变量与自动生成的代码进行绑定,即调用我们自动生成的代码。
那么我们还是来看下butterknife-bind模板库的结构:
只有Butterknife一个类,在这之前我们还需将前面我们已经定义好的module引入
dependencies {...compile project(path: ':butterknife-annotations')
}
有了之前的基础,我们Make Project项目工程,之后就可以找到MainActivity$Binding类,或者直接在/app/build/generated/source/kapt/debug/目录下查找。
Bind
MainActivity$Binding在构造方法中就已经调用了我们的需要的bindView与setOnClickListener方法。所以我们需要使用的话只需实例化即可。但由于我们是该类是通过注解处理器自动生成的,所以我们并不知道它的类名全称(这里我们相当于查看了源码,才知道是以$Binding结尾)。这样我们是不能通过new关键字来实例化。如此,我们又该如何实例化它呢?这时我们再来看butterknife-bind中的唯一的类Butterknife
public class Butterknife {private Butterknife() {}private static <T extends Activity> void initialization(T target, String suffix) {Class<?> tClass = target.getClass();String className = tClass.getName();try {Class<?> bindingClass = tClass.getClassLoader().loadClass(className + suffix);Constructor<?> constructor = bindingClass.getConstructor(tClass);constructor.newInstance(target);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}public static void bind(Activity activity) {initialization(activity, ConstantUtils.BINDING_BUTTERKNIFE_SUFFIX);}
}
在initialization方法中,我们通过java反射来实例化我们需要的MainActivity$Binding。既然我们已经知道自动生成的类是由原始类(MainActivity)+后缀($Binding)组成。所以可以很好的使用java反射来实例化所需的类。对于外界的调用只需使用bind方法,传入需要绑定的类即可。
Use
到这里,所以的准备工作已经完成。接下来我们可以开始在MainActivity中使用。首先将定义的库进行依赖
dependencies {...implementation project(':butterknife-bind')kapt project(':butterknife-compiler')
}
然后在MainActivity中使用
class MainActivity : AppCompatActivity() {@BindView(R.id.public_service, R.string.public_service)lateinit var sName: TextView@BindView(R.id.personal_wx, R.string.personal_wx)lateinit var sPhone: TextViewoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)Butterknife.bind(this)}@OnClick(R.id.public_service)fun nameClick(view: View) {Toast.makeText(this, getString(R.string.public_service_click_toast), Toast.LENGTH_LONG).show()}@OnClick(R.id.personal_wx)fun phoneClick(view: View) {Toast.makeText(this, getString(R.string.personal_wx_click_toast), Toast.LENGTH_LONG).show()}
}
我们使用@BindView绑定View的Id与默认值;使用@OnClick绑定点击事件;使用Butterknife.bind(this)绑定自定义的注解代码。这样我们已经完成了与开源库Butterknife相似的功能。
progurad
现在你在模拟器或者真机上跑着非常完美,然后你不小心切换到release版本并且开启了混淆功能。这时你会发现mmp居然没有效果。为什么呢?debug与release的区别,绝大数情况下都是混淆惹的祸。我们在实例化自动生成的类时使用的是java反射机制,所以一旦混淆了我们的java反射就找不到我们指定的类名,这样自然也就没有效果了。
那么我们现在又该如何解决呢?别急,是否还记得在系列的Part1我们自定义注解变量中定义了@Keep。
在MainActivity$Binding类上我们使用了@Keep来标识该类,通过该标识告诉proguard不去混淆使用@Keep标记的类。要达到这种效果,我们还需经过以下两个步骤:
1.在butterknife-bind的proguard-rules.pro文件中添加如下代码
-keep class com.idisfkj.butterknife.annotations.Keep**
-keep @com.idisfkj.butterknife.annotations.Keep public class *
-keepclassmembers @com.idisfkj.butterknife.annotations.Keep class ** {*;}
2.为了是依赖库的混淆生效,我们还需使用consumerProguardFiles声明
defaultConfig {...consumerProguardFiles 'proguard-rules.pro' //依赖库混淆生效}
完成这两步后我们在重新构建release版本,这时程序完美运行。终于可以轻松的休息会了!
End
自定义Android注解系列完美收工,希望通过这三部曲能够帮助大家学会如何实现注解库。最后希望大家点赞支持一下,谢谢!
文章中的代码都可以在Github中获取到。使用时请将分支切换到feat_annotation_processing
相关文章
自定义Android注解Part1:注解变量
自定义Android注解Part2:代码自动生成
关注
公众号:怪谈时间到了
自定义Android注解Part3:绑定相关推荐
- 自定义Android注解Part2:代码自动生成
上一期我们已经把butterknife-annotations中的注解变量都已经定义好了,分别为BindView.OnClick与Keep. 如果你是第一次进入本系列文章,强烈推荐跳到文章末尾查看上篇 ...
- 开发自己的山寨Android注解框架
目录 开发自己的山寨Android注解框架 开发自己的山寨Android注解框架 参考 Github黄油刀 Overview 在上一章我们学习了Java的注解(Annotation),但是我想大家可能 ...
- 玩转java(Android)注解
2019独角兽企业重金招聘Python工程师标准>>> 玩转java(Android)注解 1. java标准(原生)注解概览 Java API 中,在java.lang.java. ...
- Android应用程序绑定服务(bindService)的过程源代码分析
Android应用程序组件Service与Activity一样,既可以在新的进程中启动,也可以在应用程序进程内部启动:前面我们已经分析了在新的进程中启动Service的过程,本文将要介绍在应用程序内部 ...
- 自定义依赖注解无效_关于Apt注解实践与总结【包含20篇博客】
超详细!安卓巴士开发者大会嘉宾及主题介绍 目录介绍 00.注解系列博客汇总 01.什么是apt 02.annotationProcessor和apt区别 03.项目目录结构 04.该案例作用 05.使 ...
- Android 注解与注解处理器简述
Android 注解与注解处理器简述 前言 正文 一.注解 ① 注解类型 ② 注解生命周期 ③ 注解参数 二.注解处理器 ① 注册 ② 配置 三.使用 ① 接口 ② 反射 ③ 使用 ④ 强化 四.源码 ...
- Android 注解处理器使用攻略
上一篇写了JavaPoet使用攻略,了解了JavaPoet用法.那么我们就可以结合今天的Annotation Processing Tool(APT)来自定义注解处理器. 注解处理器简单解释就是收集我 ...
- Android注解之从入门到并没有放弃
定义 注解是代码里的特殊标记,这些标记可以在编译.类加载.运行时被读取,并执行相应的处理. 分类 注解分为标准注解和元注解: 标准注解 @Override:对覆盖超类中的方法进行标记,如果被标记的方法 ...
- Android注解处理器APT技术简介
Android注解处理器APT技术简介 APT是什么 例子 APT有什么用 (好处) APT原理 (为什么) APT实践 (怎么做) 参考 APT是什么 APT全称"Annotation P ...
最新文章
- python3遍历电子表格_python 3读取多个文本写入同一个excel,每个文本对应各自独立的 sheet 页...
- jQuery的选择器分类
- 自学linux指令分析-find
- JQuery常用的代码片段
- winform直接控制云台_速学指南,2分钟学会Feiyu pocket口袋云台的隐藏功能操作
- php显示时间,php实现用已经过去多长时间的方式显示时间
- 三议(巧用:before和inline-block伪元素解决)跨浏览器不定长宽,中心为基点,百分比定位~...
- spark学习-scala版写的SparkSQL程序读取Hbase表注册成表SQL查询
- Hadoop源码篇--Reduce篇
- 饭卡管理系统学生E-R图
- Lenovo System x 硬件Windows Server驱动下载
- 美团点评 2019校招 前端方向职位试卷在线考试
- 轻轻松松背单词软件测试,完美单词王app
- php面试会考计算机网络,计算机网络常见面试题整理
- Altium Designer2019——PCB 设计叠层说明
- mac go版本升级
- 第一部分day5 文件操作
- 蓝牙耳机哪款好用?这些选购小技巧帮你选到更适合你的蓝牙耳机!
- 软件体系结构的第二次实验(解释器风格与管道过滤器风格)
- 第九章SpringBoot整合Spring Data JPA
热门文章
- Uber无人车撞人视频公布,究竟哪儿出问题了?
- 人人都是作曲家:基于深度神经网络的音乐风格迁移
- 重磅 | 机器学习大神Bengio最新论文发布,专注RNN优化难题,将在NIPS提出新概念fraternal dropout
- 系统、应用监控的缜密思路,性能瓶颈的克星
- 高并发下秒杀商品,你必须知道的9个细节
- 实现数据“一键脱敏”,Sharding Sphere帮你搞定
- 非常有必要了解的Springboot启动扩展点
- 没有这 29 款插件的 Chrome 是没有灵魂的!
- 5分钟带你读「大清」微积分!160多年前清朝数学家撰写文言文版高等数学
- 清华旷视:让VGG再次伟大!