Android注解使用之ButterKnife 8.0详解

前言:

App项目开发大部分时候还是以UI页面为主,这时我们需要调用大量的findViewById以及setOnClickListener等代码,控件的少的时候我们还能接受,控件多起来有时候就会有一种想砸键盘的冲动。所以这个时候我们想着可以借助注解的方式让我们从这种繁重的工作中脱离出来,也让代码变得更加简洁,便于维护,今天主要学习一下只专注View、Resource、Action注解框架ButterKnife。

ButterKnife介绍

ButterKnife是一个专注于Android系统的View、Resource、Action注入框架。

官网:http://jakewharton.github.io/butterknife/

gitHub:https://github.com/JakeWharton/butterknife/

ButterKnife使用前后对比:

看看没有使用View注解之前我们是如何做的

1.)使用之前

public class ExampleActivity extends AppCompatActivity {
 private final static String TAG = ExampleActivity.class.getSimpleName();
 String butterKnifeStr;
 Drawable butterKnifeDrawable;
 Button butterKnifeBtn;
 ImageView butterKnifeIv;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_butter_knife);
  initResource();
  initViews();
 }

 private void initViews() {
  butterKnifeBtn = (Button) findViewById(R.id.btn_butter_knife);
  butterKnifeBtn.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    Log.e(TAG, "onButterKnifeBtnClick");
   }
  });
  butterKnifeIv = (ImageView) findViewById(R.id.iv_butter_knife);
  butterKnifeBtn.setText(butterKnifeStr);
  butterKnifeIv.setImageDrawable(butterKnifeDrawable);
 }

 private void initResource() {
  butterKnifeStr = getString(R.string.title_btn_butter_knife);
  butterKnifeDrawable = getDrawable(R.mipmap.ic_launcher);
 }
}

2.)使用之后

public class ButterKnifeActivity extends AppCompatActivity {
 private final static String TAG = ButterKnifeActivity.class.getSimpleName();
 private Unbinder unbinder;
 @BindString(R.string.title_btn_butter_knife)
 String butterKnifeStr;
 @BindDrawable(R.mipmap.ic_launcher)
 Drawable butterKnifeDrawable;
 @BindView(R.id.btn_butter_knife)
 Button butterKnifeBtn;
 @BindView(R.id.iv_butter_knife)
 ImageView butterKnifeIv;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_butter_knife);
  unbinder = ButterKnife.bind(this);
  initViews();
 }

 private void initViews() {
  butterKnifeBtn.setText(butterKnifeStr);
  butterKnifeIv.setImageDrawable(butterKnifeDrawable);
 }

 @OnClick(R.id.btn_butter_knife)
 public void onButterKnifeBtnClick(View view) {
  Log.e(TAG, "onButterKnifeBtnClick");
 }

 @Override
 protected void onDestroy() {
  super.onDestroy();
  unbinder.unbind();
 }
}

3.)ButterKnife 优势

通过上面使用前后对比来分析下ButterKnife优势

  • 强大的View绑定和Click事件处理功能,简化代码,提升开发效率
  • 方便的处理Adapter里的ViewHolder绑定问题
  • 运行时不会影响APP效率,使用配置方便
  • 代码清晰,可读性强

使用前后对比之后有没有觉得非常的简单易用。接下来来看下具体怎么使用的?

ButterKnife如何使用:

1).在Project的build.gradle中添加如下配置

buildscript {
 repositories {
 mavenCentral()
 }
 dependencies {
 classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
 }
}

2.)在Module的build.gradle添加如下配置

apply plugin: 'com.neenbedankt.android-apt'

android {
 ...
}

dependencies {
 compile 'com.jakewharton:butterknife:8.1.0'
 apt 'com.jakewharton:butterknife-compiler:8.1.0'
}

3.)注入和重置注入

Activity

class ExampleActivity extends Activity {
 @BindView(R.id.title) TextView title;
 @BindView(R.id.subtitle) TextView subtitle;
 @BindView(R.id.footer) TextView footer;

 @Override public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.simple_activity);
 ButterKnife.bind(this);
 // TODO Use fields...
 }
}

Fragment:由于不同的视图生命周期,所以需要在onCreateView bind,在onDestroyView unbind

public class FancyFragment extends Fragment {
 @BindView(R.id.button1) Button button1;
 @BindView(R.id.button2) Button button2;
 private Unbinder unbinder;

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 View view = inflater.inflate(R.layout.fancy_fragment, container, false);
 unbinder = ButterKnife.bind(this, view);
 // TODO Use fields...
 return view;
 }

 @Override public void onDestroyView() {
 super.onDestroyView();
 unbinder.unbind();
 }
}

ViewHolder

public class MyAdapter extends BaseAdapter {
 @Override public View getView(int position, View view, ViewGroup parent) {
 ViewHolder holder;
 if (view != null) {
  holder = (ViewHolder) view.getTag();
 } else {
  view = inflater.inflate(R.layout.whatever, parent, false);
  holder = new ViewHolder(view);
  view.setTag(holder);
 }

 holder.name.setText("John Doe");
 // etc...

 return view;
 }

 static class ViewHolder {
 @BindView(R.id.title) TextView name;
 @BindView(R.id.job_title) TextView jobTitle;

 public ViewHolder(View view) {
  ButterKnife.bind(this, view);
 }
 }
}

4.)view注入 @BindView,@BindViews

@BindView(R.id.btn_butter_knife)
Button butterKnifeBtn;
@BindViews({R.id.tv_butter_knife1,R.id.tv_butter_knife2,R.id.tv_butter_knife3})
List<TextView> textViews;

5.)Resource注入

@BindString(R.string.title_btn_butter_knife)
 String butterKnifeStr;//string注解使用
 @BindDrawable(R.mipmap.ic_launcher)
 Drawable butterKnifeDrawable;//Drawable注解使用
 @BindBitmap(R.mipmap.ic_launcher)
 Bitmap butterKnifeBitmap;;//Bitmap注解使用
 @BindArray(R.array.day_of_week)
 String weeks[];//数组
 @BindColor(R.color.colorPrimary)
 int colorPrimary;//color注解使用
 @BindDimen(R.dimen.activity_horizontal_margin)
 Float spacer;

6).单事件注入

一个控件指定一个事件回调

 /**
  * 带参数
  */
 @OnClick(R.id.btn_butter_knife)
 public void onButterKnifeBtnClick() {
 }

 /**
  * 带参数
  */
 @OnClick(R.id.btn_butter_knife)
 public void onButterKnifeBtnClick(View view) {
  Log.e(TAG, "onButterKnifeBtnClick");
 }

 /**
  * 带参数
  * @param button
  */
 @OnClick(R.id.btn_butter_knife)
 public void onButterKnifeBtnClick(Button button) {
  Log.e(TAG, "onButterKnifeBtnClick");
 }

也可以多个控件指定一个事件回调

 /**
  * 两个不同的button都相应onButterKnifeBtnClick事件回调
  *
  * @param button
  */
 @OnClick({R.id.btn_butter_knife, R.id.btn_butter_knife1})
 public void onButterKnifeBtnClick(Button button) {
  Log.e(TAG, "onButterKnifeBtnClick");
 }

自定义的控件不通过ID也可以绑定到自己的事件

public class FancyButton extends Button {
 @OnClick
 public void onClick() {
 // TODO do something!
 }
}

7.)多事件回调

有一些View的listener是有多个回调方法的,比如EditText添加addTextChangedListener

 editText.addTextChangedListener(new TextWatcher() {
   @Override
   public void beforeTextChanged(CharSequence s, int start, int count, int after) {

   }

   @Override
   public void onTextChanged(CharSequence s, int start, int before, int count) {

   }

   @Override
   public void afterTextChanged(Editable s) {

   }
  });

可以使用注解方式改成如下

 @OnTextChanged(value = R.id.nameEditText, callback = OnTextChanged.Callback.BEFORE_TEXT_CHANGED)
 void beforeTextChanged(CharSequence s, int start, int count, int after) {

 }
 @OnTextChanged(value = R.id.nameEditText, callback = OnTextChanged.Callback.TEXT_CHANGED)
 void onTextChanged(CharSequence s, int start, int before, int count) {

 }
 @OnTextChanged(value = R.id.nameEditText, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
 void afterTextChanged(Editable s) {

 }

8.)选择性注入

默认情况下,@Bind 和listener的注入都是必须的,如果target view没有被发现,则会报错. 为了抑制这种行为,可以用@Optional注解来标记field和方法,让注入变成选择性的,如果targetView存在,则注入, 不存在,则什么事情都不做.或者使用 Android's "support-annotations" library.中的@Nullable来修饰

@Nullable @BindView(R.id.might_not_be_there)
TextView mightNotBeThere;

@Optional @OnClick(R.id.maybe_missing)
void onMaybeMissingClicked() {
 // TODO ...
}

9.)ButterKnife.apply()函数

可以通过ButterKnifeapply()函数对view集合元素或者单个view的Action, Setter和Property进行修改

ButterKnife.apply(nameViews, DISABLE);
ButterKnife.apply(nameViews, ENABLED, false);

static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {
 @Override public void apply(View view, int index) {
 view.setEnabled(false);
 }
};
static final ButterKnife.Setter<View, Boolean> ENABLED = new ButterKnife.Setter<View, Boolean>() {
 @Override public void set(View view, Boolean value, int index) {
 view.setEnabled(value);
 }
};

ButterKnife.apply(nameViews, View.ALPHA, 0.0f);

10.)ButterKnife.findById()

ButterKnife 也提供了findById函数,通过findById()可以获取Activity、Dialog、View中的view,并且是泛型类型不需要强转

View view = LayoutInflater.from(context).inflate(R.layout.thing, null);
TextView firstName = ButterKnife.findById(view, R.id.first_name);
TextView lastName = ButterKnife.findById(view, R.id.last_name);
ImageView photo = ButterKnife.findById(view, R.id.photo);

ButterKnife自动生成插件安装:

在AndroidStudio->File->Settings->Plugins->搜索Zelezny下载添加就行 ,可以快速生成对应组件的实例对象,不用手动写。使用时,在要导入注解的Activity 或 Fragment 或 ViewHolder的layout资源代码上,右键——>Generate——Generate ButterKnife Injections,然后就出现如图的选择框。

插件gitHub地址:https://github.com/avast/android-butterknife-zelezny

上面给了一个使用流程图,不过流程图不会针对最新的8.0.1版本的,但是都是差不多的

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android 中的注解详细介绍

    注解是我们经常接触的技术,Java有注解,Android也有注解,本文将试图介绍Android中的注解,以及ButterKnife和Otto这些基于注解的库的一些工作原理. 归纳而言,Android中的注解大概有以下好处 提高我们的开发效率 更早的发现程序的问题或者错误 更好的增加代码的描述能力 更加利于我们的一些规范约束 提供解决问题的更优解 准备工作 默认情况下,Android中的注解包并没有包括在framework中,它独立成一个单独的包,通常我们需要引入这个包. dependencies

  • Android AOP 注解详解及简单使用实例(三)

    Android  注解 相关文章: Android AOP注解Annotation详解(一) Android AOP之注解处理解释器详解(二) Android AOP 注解详解及简单使用实例(三) 一.简介 在Android 里面 注解主要用来干这么几件事: 和编译器一起给你一些提示警告信息. 配合一些ide 可以更加方便快捷 安全有效的编写Java代码.谷歌出的support-annotations这个库 就是主要干这个的. 和反射一起 提供一些类似于spring 可配置的功能,方便简洁. 二

  • Android注解框架对比分析

    Java的注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记,标记可以加在包,类,属性,方法,本地变量上.然后你可以写一个注解处理器去解析处理这些注解(人称编译时注解),也可以在程序运行时利用反射得到注解做出相应的处理(人称运行时注解). 开发Android程序时,没完没了的findViewById, setOnClickListener等等方法,已经让大多数开发者头疼不已.好在市面上有所谓的注解框架可以帮助开发者简化一些过程.比较流行的有butterknife

  • Android 中的注解深入探究

    本文系GDG Android Meetup分享内容总结文章 注解是我们经常接触的技术,Java有注解,Android也有注解,本文将试图介绍Android中的注解,以及ButterKnife和Otto这些基于注解的库的一些工作原理. 归纳而言,Android中的注解大概有以下好处 提高我们的开发效率 更早的发现程序的问题或者错误 更好的增加代码的描述能力 更加利于我们的一些规范约束 提供解决问题的更优解 准备工作 默认情况下,Android中的注解包并没有包括在framework中,它独立成一个

  • Android注解ButterKnife的基本使用

    ButterKnife的最新版本是8.4.0. 首先,需要导入ButterKnife的jar包. 在AndroidStudio中,File->Project Structure->Dependencies->Library dependency 搜索butterknife即可,第一个就是. 另外一种就是直接在build:grade(app)dependencies里添加: compile 'com.jakewharton:butterknife:8.4.0' annotationProc

  • 深入分析安卓(Android)中的注解

    归纳而言,Android中的注解大概有以下好处 1.提高我们的开发效率 2.更早的发现程序的问题或者错误 3.更好的增加代码的描述能力 4.更加利于我们的一些规范约束 5.提供解决问题的更优解 准备工作 默认情况下,Android中的注解包并没有包括在framework中,它独立成一个单独的包,通常我们需要引入这个包. dependencies { compile 'com.android.support:support-annotations:22.2.0' } 但是如果我们已经引入了 app

  • Android中封装SDK时常用的注解总结

    前言 在工作中我们经常需要将功能模块封装成库供合作厂商调用, 如何写好一个健壮的Android Library有很多讲究,使用注解可以对SDK暴露给开发者的接口做出一些限制,从而尽可能地避免开发者错误地使用API. 下面我们介绍几种封装SDK时常用到的注解,需要的朋友们可以参考学习. 一.IntDef与StringDef 我们有时候会使用int常量或者String常量来代替枚举, 特别在你编写SDK的时候,你可以通过IntDef或者StringDef来限制接口可接受的参数. 比如,有一个 dis

  • Android AOP注解Annotation详解(一)

    Android 注解Annotation 相关文章: Android AOP注解Annotation详解(一) Android AOP之注解处理解释器详解(二) Android AOP 注解详解及简单使用实例(三) Android AOP 等在Android上应用越来越广泛,例如框架ButterKnife,Dagger2,EventBus3等等,这里我自己总结了一个学习路程. - Java的注解Annotation - 注解处理解析器APT(Annotation Processing Tool)

  • Android AOP之注解处理解释器详解(二)

    Android APO 注解处理解释器 相关文章: Android AOP注解Annotation详解(一) Android AOP之注解处理解释器详解(二) Android AOP 注解详解及简单使用实例(三) 一.提取Annotation信息 当开发者使用了Annotation修饰了类.方法.Field等成员之后,这些Annotation不会自己生效,必须由开发者提供相应的代码来提取并处理Annotation信息.这些处理提取和处理Annotation的代码统称为APT(Annotation

  • Android注解使用之ButterKnife 8.0详解

    前言: App项目开发大部分时候还是以UI页面为主,这时我们需要调用大量的findViewById以及setOnClickListener等代码,控件的少的时候我们还能接受,控件多起来有时候就会有一种想砸键盘的冲动.所以这个时候我们想着可以借助注解的方式让我们从这种繁重的工作中脱离出来,也让代码变得更加简洁,便于维护,今天主要学习一下只专注View.Resource.Action注解框架ButterKnife. ButterKnife介绍 ButterKnife是一个专注于Android系统的V

  • Android安装apk文件并适配Android 7.0详解

    Android安装apk文件并适配Android 7.0详解 首先在AndroidManifest.xml文件,activity同级节点注册provider: <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.file_provider" android:exported="false"

  • Android开发Jetpack组件DataBinding用例详解

    目录 简介 使用方式 1. build.gradle 中添加 kapt,并启用dataBinding 2.修改布局文件,添加 layout 和 data 标签 3.使用 DataBindingUtil 绑定布局 4.布局的 data 标签中添加数据变量,并使用其参数 5.BindingAdapter的使用 简介 DataBinding 是 Jetpack 组件之一,适用于 MVVM 模式开发,也是Google官方推荐使用的组件之一.使用DataBinding可以很容易的达到视图与逻辑分离,直接在

  • Android JetPack组件的支持库Databinding详解

    目录 简介 启用databinding 布局xml variable (变量标签) data (数据标签) @{}表达式 绑定普通数据 绑定可观察数据 对单个变量的绑定-fields 对集合的绑定-collections 绑定对象-objects 绑定LiveData 双向绑定 简介 DataBinding 是 Google 在 Jetpack 中推出的一款数据绑定的支持库,利用该库可以实现在页面组件中直接绑定应用程序的数据源.使其维护起来更加方便,架构更明确简介. DataBinding 唯一

  • Android 通过网络图片路径查看图片实例详解

    Android 通过网络图片路径查看图片实例详解 1.在项目清单中添加网络访问权限 <!--访问网络的权限--> <uses-permission android:name="android.permission.INTERNET"/> 2.获取网络图片数据 /** * 获取网络图片的数据 * @param path 网络图片路径 * @return * @throws Exception */ public static byte[] getImage(Str

  • Android Naive与WebView的互相调用详解

    Android  Naive与WebView的互相调用详解 Android的Naive程序是可以嵌套WebView,并且可以做到与WebView的交互,一般来说有两种方法,一是直接交互,比如,Naive直接调用WebView的方法和WebView直接调用Naive的方法.二是WebView可以写<a/>超链接标签,然后用户点击此标签时,Naive可以拦截到点击标签的事件,这样,我们可以在链接上做一套自己的协议,然后Android和iOS可以根据此协议做出相同的处理,做到多平台统一. 我们先研究

  • Android 自定义imageview实现图片缩放实例详解

    Android 自定义imageview实现图片缩放实例详解 觉得这个自定义的imageview很好用 性能不错  所以拿出来分享给大家  因为不会做gif图  所以项目效果 就不好贴出来了  把代码贴出来 1.项目结构图 2.Compat.class package com.suo.image; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.view.View; pu

  • Android xmlns 的作用及其自定义实例详解

     Android xmlns 的作用及其自定义实例详解 xmlns:Android="http://schemas.android.com/apk/res/android的作用是: 这个是xml的命名空间,有了他,你就可以alt+/作为提示,提示你输入什么,不该输入什么,什么是对的,什么是错的,也可以理解为语法文件.或者语法判断器什么的 这个主要作用是在运行的时候那些控件的属性都是通过它来识别的,如果上面你写错了,不会有任何问题,但是在运行的时候就会有问题,提示你没有指定宽度等什么.这个是不用联

  • Android 开发中使用Linux Shell实例详解

    Android 开发中使用Linux Shell实例详解 引言 Android系统是基于Linux内核运行的,而做为一名Linux粉,不在Android上面运行一下Linux Shell怎么行呢? 最近发现了一个很好的Android Shell工具代码,在这里分享一下. Shell核心代码 import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.

  • Android Activity的跳转与传值详解

    Android Activity的跳转与传值详解 Activity跳转与传值,主要是通过Intent类来连接多个Activity,以及传递数据. Intent是Android一个很重要的类.Intent直译是"意图",什么是意图呢?比如你想从这个Activity跳转到另外一个Activity,这就是一个意图.Intent类在Android系统中的作用很大,在此不详细说了,后面有文章介绍! Activity跳转,无返回结果 这是最简单的Activity跳转方式.从一个Activity启动

随机推荐