ButterKnife的使用详解

今天来讲解一下注解框架ButterKnife,此框架由Android之神Jake Wharton开源的。

GitHub的链接地址:https://github.com/JakeWharton/butterknife

ButterKnife框架的优点:

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

一、在项目中导入ButterKnife

1、找到项目的app下的build.grade,直接添加下面两行依赖,刷新即可

dependencies {
    compile 'com.jakewharton:butterknife:8.5.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
}

2、在项目的build.gradle中添加

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

3、在主程序依赖Module的build.gradle中添加

apply plugin: 'com.android.library'
apply plugin: 'com.jakewharton.butterknife'

注意:在依赖Module中使用,声明注解时用R2替代R, 例如:

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

二、绑定ButterKnife

1.在Activity中绑定

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //绑定ButterKnife
        ButterKnife.bind(this);
    }
}

2.在Fragment中绑定

注意:Fragment的生命周期不同于activity,在onCreateView中绑定一个Fragment时,在onDestroyView中将视图设置为null。当你调用bind来为你绑定一个Fragment时,Butter Knife会返回一个Unbinder的实例。在适当的生命周期(onDestroyView)回调中调用它的unbind方法进行Fragment解绑。

public class FirstFragment extends Fragment {

    private Unbinder unbinder;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_first, null);
        //绑定
        unbinder = ButterKnife.bind(this, view);

        return view;
    }

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

3.在ViewHolder中绑定

    static class ViewHolder {
        @BindView(R.id.btnOne)
        TextView btnOne;
        @BindView(R.id.imgOne)
        TextView imgOne;

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

三、绑定注解

名称解析
@BindView绑定一个view id为一个view 变量
@BindViews绑定多个view id为一个view的list变量
@BindArray绑定string里面array数组,@BindArray(R.array.city ) String[] citys ;
@BindBitmap绑定图片资源为Bitmap,@BindBitmap( R.mipmap.wifi ) Bitmap bitmap;
@BindBool绑定真假boolean
@BindColor绑定color,@BindColor(R.color.colorAccent) int black;
@BindDimen绑定Dimen,@BindDimen(R.dimen.borth_width) int mBorderWidth;
@BindDrawable绑定Drawable,@BindDrawable(R.drawable.test_pic) Drawable mTestPic;
@BindFloat绑定float
@BindInt绑定int
@BindString绑定一个String id为一个String变量,@BindString( R.string.app_name ) String meg;

1. @BindView 绑定一个View

    @BindView(R.id.btnOne)
    public Button btnOne;

    @BindView(R.id.imgOne)
    public ImageView imgOne;

2. @BindViews 绑定多个View

public class MainActivity extends AppCompatActivity {

    @BindViews({R.id.btnOne,R.id.btnTwo,R.id.btnThree})
    public List<Button> btnList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //绑定ButterKnife
        ButterKnife.bind(this);

        btnList.get(0).setText("按钮One");
        btnList.get(1).setText("按钮Two");
        btnList.get(2).setText("按钮Three");
    }
}

3. @BindArray 绑定绑定string里面array数组

先在String文件中添加一个array数组

<resources>
    <string name="app_name">ButterKnifeDemo</string>

    <string-array name="language">
        <item>Java</item>
        <item>Kotlin</item>
        <item>C</item>
        <item>C++</item>
        <item>PHP</item>
        <item>JavaScript</item>
    </string-array>

</resources>

而后直接绑定使用

public class MainActivity extends AppCompatActivity {

    @BindArray(R.array.language)
    String[] language;

    @BindViews({R.id.btnOne,R.id.btnTwo,R.id.btnThree})
    public List<Button> btnList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //绑定ButterKnife
        ButterKnife.bind(this);

        btnList.get(0).setText(language[0]);
        btnList.get(1).setText(language[1]);
        btnList.get(2).setText(language[2]);
    }
}

4. @BindBitmap 绑定资源图片

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.imgOne)
    public ImageView imgOne;

    @BindBitmap(R.drawable.ic_launcher)
    public Bitmap ic_launcher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //绑定ButterKnife
        ButterKnife.bind(this);

        imgOne.setImageBitmap(ic_launcher);
    }
}

5. @BindBool 绑定真假boolean

新建一个资源文件bool.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <bool name="isPlay">true</bool>
    <bool name="isDo">false</bool>

</resources>

使用情况

    @BindBool(R.bool.isPlay)
    public boolean isPlay;

6. @BindColor 绑定color

    @BindColor(R.color.colorAccent)
    int colorAccent;

7. @BindDimen 绑定Dimen

先添加一个dimen.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="textview_height">25dp</dimen>
    <dimen name="textview_width">150dp</dimen>
    <dimen name="ball_radius">3dp</dimen>
    <dimen name="font_size">16sp</dimen>
</resources>

使用情况

    @BindDimen(R.dimen.font_size)
    int font_size;

8. @BindDrawable 绑定Drawable

@BindDrawable(R.drawable.ic_launcher_background)
Drawable ic_launcher_background;

9. @BindFloat 绑定Float

    @BindFloat(R.dimen.font_size)
    float font_size;

10. @BindInt 绑定Int

先添加一个资源文件integer.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="max_value">99</integer>
    <integer name="min_value">1</integer>
</resources>

使用情况

    @BindInt(R.integer.max_value)
    int max_value;

11. @BindString 绑定一个String

@BindString( R.string.app_name ) 
String appName;




四、事件注解

名称作用
@OnClick点击事件
@OnLongClick长按事件
@OnCheckedChanged选中,取消选中
@OnEditorAction软键盘的功能键
@OnFocusChange焦点改变
@OnItemClickitem被点击(注意这里有坑,如果item里面有Button等这些有点击的控件事件的,需要设置这些控件属性focusable为false)
@OnItemLongClickitem长按(返回真可以拦截onItemClick)
@OnItemSelecteditem被选择事件
@OnPageChange页面改变事件
@OnTextChangedEditText里面的文本变化事件
@OnTouch触摸事件
@Optional选择性注入,如果当前对象不存在,就会抛出一个异常,为了压制这个异常,可以在变量或者方法上加入一下注解,让注入变成选择性的,如果目标View存在,则注入, 不存在,则什么事情都不做=如下代码

1. @OnClick 绑定点击事件

    @OnClick(R.id.btnOne)
    public void btnOne(View view) {
    }

    //无参
    @OnClick(R.id.btnOne)
    public void btnOne() {
    }

    // 任意参数,默认强转,可为绑定View的子类
    @OnClick(R.id.btnOne)
    public void buttonOnClick(Button btn) {
        btn.setText("按钮1");
    }

    //绑定多个Id
    @OnClick({R.id.btnOne, R.id.btnTwo, R.id.btnThree})
    public void buttonOnClick(View view) {
        switch (view.getId()) {
            case R.id.btnOne:
                Toast.makeText(this,"按钮1",Toast.LENGTH_SHORT).show();
                break;
            case R.id.btnTwo:
                Toast.makeText(this,"按钮2",Toast.LENGTH_SHORT).show();
                break;
            case R.id.btnThree:
                Toast.makeText(this,"按钮3",Toast.LENGTH_SHORT).show();
                break;
        }
    }

    // 自定义 View,绑定自己的监听,不指定 ID
    public class MyButton extends Button {
        @OnClick
        public void onClick() {

        }
    }

2. @OnLongClick 绑定长按事件

    @OnLongClick(R.id.btnOne)
    public boolean onLongClick(View view) {

        return true;
    }

3. @OnCheckedChanged 绑定选中,取消选中

演示布局样式

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    tools:context="com.itman.butterknifedemo.MainActivity">

    <RadioGroup
        android:id="@+id/rg_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@color/white"
        android:orientation="vertical">

        <RadioButton
            android:id="@+id/rbJava"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:focusable="false"
            android:text="Java" />

        <RadioButton
            android:id="@+id/rbKotlin"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:focusable="false"
            android:text="Kotlin" />

        <RadioButton
            android:id="@+id/rbJavaScript"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:focusable="false"
            android:text="JavaScript" />
    </RadioGroup>
</LinearLayout>

使用情况:

 @OnCheckedChanged({R.id.rbJava,R.id.rbKotlin,R.id.rbJavaScript})
    public void OnCheckedChangeListener(CompoundButton view, boolean ischanged ){
        switch (view.getId()) {
            case R.id.rbJava:
                if (ischanged){//注意:这里一定要有这个判断,只有对应该id的按钮被点击了,ischanged状态发生改变,才会执行下面的内容
                    //选中,未选中变化状态的逻辑
                }
                break;
            case R.id.rbKotlin:
                if (ischanged) {
                    //选中,未选中变化状态的逻辑
                }
                break;
            case R.id.rbJavaScript:
                if (ischanged) {
                    //选中,未选中变化状态的逻辑
                }
                break;
            default:
                break;
        }
    }

4. @OnEditorAction 绑定软件盘的功能键

    @OnEditorAction(R.id.tvOne)
    public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
        return true;
    }

5. @OnFocusChange 绑定焦点改变

    @OnFocusChange(R.id.etOne)
    public void onFocusChanged(View view, boolean hasFocus) {
    }

6. @OnItemClick 绑定Item的点击事件

    @OnItemClick(R.id.lvContent)
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    }

7. @OnItemLongClick 绑定Item的长按事件

    @OnItemLongClick(R.id.lvContent)
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        return true;
    }

8. @OnItemSelected 绑定Item被选择

    //利用注解对Spinner item  作选择监听事件处理方式
    @OnItemSelected(R.id.spContent)//默认callback为ITEM_SELECTED
    public void onItemSelected(int position) {
        Toast.makeText(this, "position: " + position, Toast.LENGTH_SHORT).show();
    }
    /*
    * 注解onNothingSelected,需要在注解参数添加一个callback,
    * 注意的是Spinner中只要有数据,默认都会选中第0个数据,所以想进入到onNothingSelected()方法,就需要把Adapter中的数据都清空
    */
    @OnItemSelected(value = R.id.spContent, callback = OnItemSelected.Callback.NOTHING_SELECTED)
    public void onNothingSelected() {
        Toast.makeText(this, "Nothing", Toast.LENGTH_SHORT).show();
    }

9. @OnPageChange 绑定页面改变事件

    @OnPageChange(R.id.vpContent)
    public void onPageSelected(int position) {
    }

    @OnPageChange(value = R.id.vpContent, callback = PAGE_SCROLL_STATE_CHANGED)
    public void onPageStateChanged(int state) {
    }

    @OnPageChange(value = R.id.vpContent, callback = PAGE_SCROLLED)
    public void onPageStateChanged(int position, float positionOffset, int positionOffsetPixels) {
    }

10. @OnTextChanged 绑定EditText里面文本变化事件

    @OnTextChanged(R.id.etContent)
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

    @OnTextChanged(value = R.id.etContent, callback = BEFORE_TEXT_CHANGED)
    public void onBeforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @OnTextChanged(value = R.id.etContent, callback = AFTER_TEXT_CHANGED)
    public void onAfterTextChanged(Editable s) {
    }

11. @OnTouch 绑定触摸事件

    @OnTouch(R.id.btnOne)
    public boolean onTouch(View view, MotionEvent event) {
        return false;
    }

12. @Optional 绑定选择性注入事件

    @Optional @OnClick(R.id.maybe_missing)
    public void onMaybeMissingClicked() {

    }




五、代码混淆

-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }

-keepclasseswithmembernames class * {
    @butterknife.* <fields>;
}

-keepclasseswithmembernames class * {
    @butterknife.* <methods>;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值