• ButterKnife初探


    前言

      最近证号有时间就写了些东西,发现ButterKnife挺好用的,和大家分享一下,从此告别findViewById。

    ButterKnife 概要

    简介

      ButterKnife(黄油刀) 是一个 Android 系统的 View 注入框架,能够通过『注解』的方式来绑定 View 的属性或方法。

    比如使用它能够减少 findViewById() 的书写,使代码更为简洁明了,同时不消耗额外的性能。

    当然这样也有个缺点,就是可读性会差一些,好在 ButterKnife 比较简单,学习难度也不大。

    使用

    这里以 as Gradle 为例,为项目添加 ButterKnife,注意两个步骤都要完成:

    1、Project 的 build.gradle 添加:

    dependencies {
      classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }

    2. App 的 build.gradle 添加:

    apply plugin: 'com.neenbedankt.android-apt'
    
    dependencies {
      compile 'com.jakewharton:butterknife:8.0.1'
      apt 'com.jakewharton:butterknife-compiler:8.0.1'
    }

    重新编译一下

    对了还可以使用as插件自动生成控件注入(Android Butterknife Zelezny)用法请参考Android Butterknife Zelezny

    关于Butterknife注解用法请移步到官网Butterknife

    原理简单分析

    Java Annotation Processing

    注解处理器,在 Java5 中叫 APT,有没有很眼熟:

    dependencies {
      classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }
    
    // 引入 ButterKnifeProcessor 等 
    apt 'com.jakewharton:butterknife-compiler:8.0.1'

    这是一个用于编译时扫描和解析 Java 注解的工具,通过它我们可以自己定义注解,并定义解析器来处理它们。它的原理是读入 Java 源代码,解析注解,然后生成新的 Java 代码,新生成的代码最后被编译成 Java 字节码。

    当然这里我们不是要深究 APT 的原理,而是要知道在 ButterKnife 中运用到了这个工具。

    ButterKnife 流程

    这里以一个栗子来一步步观察,ButterKnife 的工作流程。

    在此之前看一眼 @BindView 注解的定义:

    @Retention(CLASS) @Target(FIELD)
    public @interface BindView {
      /** View ID to which the field will be bound. */
      @IdRes int value();
    }

    重点在于 @Retention(CLASS),它表示该注解在编译时被保留,但在运行时 JVM 会忽略它。因此使用 ButterKnife 的注解,不会对运行时的性能造成消耗。

    扫描 ButterKnife 注解

    首先我们使用注解来声明我们的一个 View:

    @BindView(R.id.text1) TextView text1;

    于是在我们编译的时候,ButterKnifeProcessor 类的 process() 方法便会执行,搜索到所有的 ButterKnife 注解(@BindView),然后生成一个 Java 类。

    根据注解,生成 Java 类

    我们在 appuildgeneratedsourceapt 中找到生成的 MainActivity$$ViewBinder 文件,该类中包含了一个 bind 方法:

    public Unbinder bind(final Finder finder, final T target, Object source) {
        InnerUnbinder unbinder = createUnbinder(target);
        View view;
        view = finder.findRequiredView(source, 2131492944, "field 'text1'");
        target.text1 = finder.castView(view, 2131492944, "field 'text1'");
        return unbinder;
      }

    到这里就越来越像我们手写 findViewById() 了。

    动态注入

    最后当我们执行 ButterKnife.bind(this) 时,ButterKnife 会加载上面生成的类,然后调用其 bind 方法。

    • 这里首先调用了 findRequiredView 去寻找 R.id.text1 所对应的控件,其实相当于我们的 findViewById()
    • 其次调用 castView,相当于类型转换,把找到的 View 转化为 TextView 类型

    至此,我们就完成了一次 ButterKnife 的工作流程。

    参考:

    http://www.itnose.net/detail/6291539.html

    Butterknife

  • 相关阅读:
    机器学习(深度学习)
    机器学习(六)
    机器学习一-三
    Leetcode 90. 子集 II dfs
    Leetcode 83. 删除排序链表中的重复元素 链表操作
    《算法竞赛进阶指南》 第二章 Acwing 139. 回文子串的最大长度
    LeetCode 80. 删除有序数组中的重复项 II 双指针
    LeetCode 86 分割链表
    《算法竞赛进阶指南》 第二章 Acwing 138. 兔子与兔子 哈希
    《算法竞赛进阶指南》 第二章 Acwing 137. 雪花雪花雪花 哈希
  • 原文地址:https://www.cnblogs.com/earl-yongchang/p/6142899.html
Copyright © 2020-2023  润新知