ButterKnife使用详解

来源:互联网 发布:九年级下册历史书淘宝 编辑:程序博客网 时间:2024/05/11 08:54


写在前面:该文档使用7.0版本,8.0版本方法名有所改动,建议看官方文档,整体业务逻辑和原理没什么变动,官网

在Android编程过程中,我们会写大量的布局和点击事件,像初始view、设置view监听这样简单而重复的操作让人觉得麻烦类,所以可以采用注解的方式去实现,而ButterKnife则是注解中相对简单易懂的很不错的开源框架,而网上的文档和例子都过时了,7.0之后的版本改动很大,之前的注解都不能用了,所以借鉴官方文档总结了一下,接下来就介绍一下如何使用。基本参照官方文档,加上自己的心得。


ButterKnife 优势:

1.强大的View绑定和Click事件处理功能,简化代码,提升开发效率

2.方便的处理Adapter里的ViewHolder绑定问题

3.运行时不会影响APP效率,使用配置方便

4.代码清晰,可读性强


使用心得:

1.Activity ButterKnife.bind(this);必须在setContentView();之后,且父类bind绑定后,子类不需要再bind

2.Fragment ButterKnife.bind(this, mRootView);

3.属性布局不能用private or static 修饰,否则会报错

4.setContentView()不能通过注解实现。(其他的有些注解框架可以)


使用步骤:

一.导入ButterKnife jar包:

1)如果你是Eclipse,可以去官网下载jar包
2)如果你是AndroidStudio可以直接 File->Project Structure->Dependencies->Library dependency 搜索butterknife即可,第一个就是
3)当然也可以用maven和gradle配置

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. MAVEN  
  2.     <dependency>  
  3.       <groupId>com.jakewharton</groupId>  
  4.       <artifactId>butterknife</artifactId>  
  5.       <version>(insert latest version)</version>  
  6.     </dependency>  
  7.   
  8. GRADLE  
  9. compile 'com.jakewharton:butterknife:(insert latest version)'  
  10.   
  11. Be sure to suppress this lint warning in your build.gradle.(关闭)  
  12. lintOptions {  
  13.   disable 'InvalidPackage'  
  14. }  


注意如果在Library 项目中使用要按如下步骤(github中有具体描述)否则无法找到view:

Configure your project-level build.gradle to include the 'android-apt' plugin:

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

Then, apply the 'android-apt' plugin in your module-level build.gradle and add the Butter Knife dependencies:

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

Note: If you are using the new Jack compiler with version 2.2.0 or newer you do not need the 'android-apt' plugin and can instead replace apt with annotationProcessor when declaring the compiler dependency.

Snapshots of the development version are available in Sonatype's snapshots repository.

Library projects

To use Butter Knife in a library, add the plugin to your buildscript:

buildscript {  repositories {    mavenCentral()   }  dependencies {    classpath 'com.jakewharton:butterknife-gradle-plugin:8.2.1'  }}

and then apply it in your module:

//apply plugin: 'com.android.library'//注意这里不要加apply plugin: 'com.jakewharton.butterknife'

Now make sure you use R2 instead of R inside all Butter Knife annotations.

class ExampleActivity extends Activity {  @BindView(R2.id.user) EditText username;  @BindView(R2.id.pass) EditText password;...}

注:官网github也有对应的引用步骤。


二.常见使用方法:
1)由于每次都要在Activity中的onCreate绑定Activity,所以个人建议写一个BaseActivity完成绑定,子类继承即可
     注:ButterKnife.bind(this);绑定Activity 必须在setContentView之后:
     实现如下(FragmentActivity 实现一样):

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public abstract class BaseActivity extends Activity {  
  2.     public abstract int getContentViewId();  
  3.     private Unbinder unbinder;
  4.     @Override  
  5.     protected void onCreate(Bundle savedInstanceState) {  
  6.         super.onCreate(savedInstanceState);  
  7.         setContentView(getContentViewId());  
  8.         unbinder = ButterKnife.bind(this);  
  9.         initAllMembersView(savedInstanceState);  
  10.     }  
  11.   
  12.     protected abstract void initAllMembersView(Bundle savedInstanceState);  
  13.   
  14.     @Override  
  15.     protected void onDestroy() {  
  16.         super.onDestroy();  
  17.         unbinder.unbind();//解除绑定,官方文档只对fragment做了解绑
  18.     }  
  19. }  

2)绑定fragment

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public abstract class BaseFragment extends Fragment {  
  2.     public abstract int getContentViewId();  
  3.     protected Context context;  
  4.     protected View mRootView;  
  5.     private Unbinder unbinder;
  6.     @Nullable  
  7.     @Override  
  8.     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  
  9.         mRootView =inflater.inflate(getContentViewId(),container,false);  
  10.         unbinder = ButterKnife.bind(this,mRootView);//绑定framgent  
  11.         this.context = getActivity();  
  12.         initAllMembersView(savedInstanceState);  
  13.         return mRootView;  
  14.     }  
  15.   
  16.     protected abstract void initAllMembersView(Bundle savedInstanceState);  
  17.   
  18.     @Override  
  19.     public void onDestroyView() {  
  20.         super.onDestroyView();  
  21.         unbinder.unbind();//解绑  
  22.     }  
  23. }  

3)绑定view

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Bind(R.id.hello_world)  
  2. TextView mHelloWorldTextView;  
  3. @Bind(R.id.app_name)  
  4. TextView mAppNameTextView;//view  

4)绑定资源

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @BindString(R.string.app_name)  
  2. String appName;//sting  
  3. @BindColor(R.color.red)  
  4. int textColor;//颜色  
  5. @BindDrawable(R.mipmap.ic_launcher)  
  6. Drawable drawable;//drawble  
  7. @Bind(R.id.imageview)  
  8. ImageView mImageView;  
  9. @Bind(R.id.checkbox)  
  10. CheckBox mCheckBox;  
  11. @BindDrawable(R.drawable.selector_image)  
  12. Drawable selector;  

5)Adapter ViewHolder 绑定

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class TestAdapter extends BaseAdapter {  
  2.     private List<String> list;  
  3.     private Context context;  
  4.   
  5.     public TestAdapter(Context context, List<String> list) {  
  6.         this.list = list;  
  7.         this.context = context;  
  8.     }  
  9.   
  10.     @Override  
  11.     public int getCount() {  
  12.         return list==null ? 0 : list.size();  
  13.     }  
  14.   
  15.     @Override  
  16.     public Object getItem(int position) {  
  17.         return list.get(position);  
  18.     }  
  19.   
  20.     @Override  
  21.     public long getItemId(int position) {  
  22.         return position;  
  23.     }  
  24.   
  25.     @Override  
  26.     public View getView(int position, View convertView, ViewGroup parent) {  
  27.         ViewHolder holder;  
  28.         if (convertView == null) {  
  29.             convertView = LayoutInflater.from(context).inflate(R.layout.layout_list_item, null);  
  30.             holder = new ViewHolder(convertView);  
  31.             convertView.setTag(holder);  
  32.         } else {  
  33.             holder = (ViewHolder) convertView.getTag();  
  34.         }  
  35.         holder.textview.setText("item=====" + position);  
  36.         return convertView;  
  37.     }  
  38.   
  39.     static class ViewHolder {  
  40.         @Bind(R.id.hello_world)  
  41.         TextView textview;  
  42.   
  43.         public ViewHolder(View view) {  
  44.             ButterKnife.bind(this, view);//绑定  
  45.         }  
  46.     }  
  47. }  

 

6)点击事件的绑定:不用声明view,不用setOnClickLisener()就可以绑定点击事件

a.直接绑定一个方法

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @OnClick(R.id.submit)  
  2. public void submit(View view) {  
  3.   // TODO submit data to server...  
  4. }  

b.所有监听方法的参数是可选的

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @OnClick(R.id.submit)  
  2. public void submit() {  
  3.   // TODO submit data to server...  
  4. }  

c.定义一个特定类型,它将自动被转换

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @OnClick(R.id.submit)  
  2. public void sayHi(Button button) {  
  3.   button.setText("Hello!");  
  4. }  

d.多个view统一处理同一个点击事件,很方便,避免抽方法重复调用的麻烦 

@OnClick({ R.id.btn_click2,R.id.btn_click3})public void more_single_click(View view) {    switch (view.getId()){        case R.id.btn_click2:            ToastUtil.shortToast(this, "btn_click2");            break;        case R.id.btn_click3:            ToastUtil.shortToast(this,"btn_click3");    }}

e.自定义view可以绑定自己的监听,不指定id

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class FancyButton extends Button {  
  2.   @OnClick  
  3.   public void onClick() {  
  4.     // TODO do something!  
  5.   }  
  6. }  

f.给EditText加addTextChangedListener(即添加多回调方法的监听的使用方法),利用指定回调,实现想回调的方法即可,哪个注解不会用点进去看下源码上的注释就会用了

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @OnTextChanged(value = R.id.mobileEditText, callback = OnTextChanged.Callback.BEFORE_TEXT_CHANGED)  
  2. void beforeTextChanged(CharSequence s, int start, int count, int after) {  
  3.   
  4. }  
  5. @OnTextChanged(value = R.id.mobileEditText, callback = OnTextChanged.Callback.TEXT_CHANGED)  
  6. void onTextChanged(CharSequence s, int start, int before, int count) {  
  7.   
  8. }  
  9. @OnTextChanged(value = R.id.mobileEditText, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)  
  10. void afterTextChanged(Editable s) {  
  11.   
  12. }  

g. view可以添加如下listener:

@OnLongClick
@OnPageChange
OnPageChange.Callback
@OnTextChanged
OnTextChanged.Callback
@OnTouch
@OnItemLongClick
@OnCheckedChanged


7)对一组View进行统一操作

a.装入一个list

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Bind({ R.id.first_name, R.id.middle_name, R.id.last_name })  
  2. List<EditText> nameViews;  

b.设置统一处理

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {  
  2.   @Override public void apply(View view, int index) {  
  3.     view.setEnabled(false);  
  4.   }  
  5. };  
  6. static final ButterKnife.Setter<View, Boolean> ENABLED = new ButterKnife.Setter<View, Boolean>() {  
  7.   @Override public void set(View view, Boolean value, int index) {  
  8.     view.setEnabled(value);  
  9.   }  
  10. };  

c.统一操作处理,例如设置是否可点,属性等

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. ButterKnife.apply(nameViews, DISABLE);  
  2. ButterKnife.apply(nameViews, ENABLED, false);  
  3. ButterKnife.apply(nameViews, ENABLED, true);

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);    }};

8)可选绑定:默认情况下,“绑定”和“监听”绑定都是必需的。如果不能找到目标视图,则将抛出异常。所以做空处理

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Nullable @Bind(R.id.might_not_be_there) TextView mightNotBeThere;  
  2.   
  3. @Nullable @OnClick(R.id.maybe_missing) void onMaybeMissingClicked() {  
  4.   // TODO ...  
  5. }  

9) 设置View的属性

Android属性也可以和apply方法一起使用。

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

10) ButterKnife.findById to find views particularly

Butter knife仍然包含了findById方法,用于仍需从一个view ,Activity,或者Dialog find view的时候。并且它可以自动转换类型。

1
2
3
4
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);

 可以import 一个 ButterKnife.findById自己玩玩。

11) @Nullable annotation

如果目标view不能找到,它将抛出异常,暗示那个field在布局中可能不存在。

1
2
@Nullable  @Bind(R.id.edUserName) 
EditText edUserName;

三、代码混淆

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. -keep class butterknife.** { *; }  
  2. -dontwarn butterknife.internal.**  
  3. -keep class **$$ViewBinder { *; }  
  4.   
  5. -keepclasseswithmembernames class * {  
  6.     @butterknife.* <fields>;  
  7. }  
  8.   
  9. -keepclasseswithmembernames class * {  
  10.     @butterknife.* <methods>;  
  11. }  

四、Zelezny插件的使用

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


1 0
原创粉丝点击