ButterKnife使用详解


写在前面:该文档使用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,然后就出现如图的选择框。(此动态图来自官网)


  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用ButterKnife,需要进行以下步骤: 1. 在项目的build.gradle文件中添加ButterKnife的依赖: ```groovy dependencies { implementation 'com.jakewharton:butterknife:10.2.3' annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3' } ``` 2. 在需要使用ButterKnife的Activity或Fragment中,使用`@BindView`注解来绑定视图元素。 ```java public class MainActivity extends AppCompatActivity { @BindView(R.id.textView) TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); // 现在可以直接使用textView了 textView.setText("Hello ButterKnife!"); } } ``` 3. 调用`ButterKnife.bind(this)`方法来完成视图的绑定。这通常是在Activity的`onCreate()`方法中进行。 4. 在需要为视图设置点击事件、长按事件等的地方,使用`@OnClick`、`@OnLongClick`等注解来定义相应的事件处理方法。 ```java public class MainActivity extends AppCompatActivity { @BindView(R.id.button) Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); // 设置点击事件处理方法 button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 处理点击事件 } }); } @OnClick(R.id.button) void onButtonClick() { // 处理点击事件,使用注解方式 } @OnLongClick(R.id.button) boolean onButtonLongClick() { // 处理长按事件,使用注解方式 return true; } } ``` 这样,你就可以使用ButterKnife来简化视图绑定和事件处理的工作了。记得在合适的时机调用`ButterKnife.unbind(this)`方法来解绑视图。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值