自定义Android注解Part3:绑定

news/2024/7/2 23:54:20

clipboard.png

上一节我们已经将自动生成注解代码部分介绍完毕,今天这篇文章是自定义Android注解系列的最后一篇文章。希望大家这一路走来有所收获。

经过前面的了解,我们三大部分:butterknife-annotations、butterknife-compiler与butterknife-bind。现在就剩下最后一部分butterknife-bind。该部分是对我们前面定义的注解变量与自动生成的代码进行绑定,即调用我们自动生成的代码。

那么我们还是来看下butterknife-bind模板库的结构:

clipboard.png

只有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:代码自动生成

关注

公众号:怪谈时间到了

clipboard.png


http://lihuaxi.xjx100.cn/news/272076.html

相关文章

python保存路径_Python IDLE的默认保存路径?

在OS X上&#xff0c;如果启动IDLE.app&#xff08;例如&#xff0c;通过双击或使用open(1)&#xff09;&#xff0c;默认目录将硬连接到~/Documents。如果要永久更改默认值&#xff0c;则需要编辑IDLE.app应用程序包中的文件idlemain.py&#xff1b;根据已安装的Python&#x…

Spring Validation最佳实践及其实现原理,参数校验没那么简单!

点击上方“方志朋”&#xff0c;选择“设为星标”回复”666“获取新整理的面试文章作者&#xff1a;六点半起床juejin.im/post/6856541106626363399之前也写过一篇关于Spring Validation使用的文章&#xff0c;不过自我感觉还是浮于表面&#xff0c;本次打算彻底搞懂Spring Val…

64% 的企业未实现智能化,5成公司算法工程师团队规模小于 10人,AI 工程师的机遇在哪里?...

整理 | 夕颜责编 | 唐小引出品 | CSDN&#xff08;ID:CSDNnews&#xff09;当前&#xff0c;人工智能技术已应用于各行各业&#xff0c;落地成为大家关注的核心问题。在经历了 2019 年的行业低谷期之后&#xff0c;无论是行业巨头还是新兴独角兽&#xff0c;都开始审视 AI 能够…

你的企业在什么情况下需要人工智能?快来看看你需要具备哪些条件与能力吧!...

作者 | Anzhela Sychyk译者 | 风车云马 责编 | 徐威龙出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;如今有关人工智能的炒作多得令人眼花缭乱。各个行业都极力采用这种技术&#xff0c;以获得相对于其他企业的竞争优势——降低运营成本&#xff0c;并改善客户体验。…

笔记本独显无输出_高价位笔记本电脑推荐(一万一以上)

全文链接&#xff1a;Rising&#xff1a;给大学生的笔记本电脑推荐​zhuanlan.zhihu.com2020.12.02已更新。本文中的部分内容参考了微信公众号"笔吧评测室"的相关文章&#xff1a;https://mp.weixin.qq.com/s/KN0270jAWNygrv64ffhiOw。1&#xff0c;移除了宏碁 Conce…

天天都会写接口(interface),但它的用途和好处有多少人能说得清楚?

点击上方“方志朋”&#xff0c;选择“设为星标”回复”666“获取新整理的面试文章作者&#xff1a;nvd11blog.csdn.net/nvd11/article/details/41129935一. 对接口的三个疑问 很多初学者都大概清楚interface是什么, 我们可以定义1个接口, 然后在里面定义一两个常量(static fin…

JAVA代码实现下载单个文件,和下载打包文件

//下载单个文件调用方法 /** * response * imgPath 下载图片地址 * fileName 保存下载文件名称 * date 2015年4月14日 下午5:53:24 */ public static void download(HttpServletResponse response,String imgPath,String fileName){ OutputStrea…

DreamWeaver做ASP 第13页

第七步&#xff1a;修改资料篇 修改资料&#xff01;首先要清醒一点&#xff0c;什么人才可以修改。 一&#xff0c;本人只能修改自己的&#xff1b;二&#xff0c;管理员可以修改所有人的。 那今天先来搞个可以修改自己资料的页面。 顺序是&#xff1a;先确认是正确登录&#…