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

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

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

<resources>
    <string name="app_name">ButterKnifeDemostring>

    <string-array name="language">
        <item>Javaitem>
        <item>Kotlinitem>
        <item>Citem>
        <item>C++item>
        <item>PHPitem>
        <item>JavaScriptitem>
    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

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


<resources>

    <bool name="isPlay">truebool>
    <bool name="isDo">falsebool>

resources>

使用情况

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

6. @BindColor 绑定color

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

7. @BindDimen 绑定Dimen

先添加一个dimen.xml文件


<resources>
    <dimen name="textview_height">25dpdimen>
    <dimen name="textview_width">150dpdimen>
    <dimen name="ball_radius">3dpdimen>
    <dimen name="font_size">16spdimen>
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


<resources>
    <integer name="max_value">99integer>
    <integer name="min_value">1integer>
resources>

使用情况

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

11. @BindString 绑定一个String

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




四、事件注解

名称 作用
@OnClick 点击事件
@OnLongClick 长按事件
@OnCheckedChanged 选中,取消选中
@OnEditorAction 软键盘的功能键
@OnFocusChange 焦点改变
@OnItemClick item被点击(注意这里有坑,如果item里面有Button等这些有点击的控件事件的,需要设置这些控件属性focusable为false)
@OnItemLongClick item长按(返回真可以拦截onItemClick)
@OnItemSelected item被选择事件
@OnPageChange 页面改变事件
@OnTextChanged EditText里面的文本变化事件
@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 绑定选中,取消选中

演示布局样式


<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.* ;
}

-keepclasseswithmembernames class * {
    @butterknife.* ;
}

你可能感兴趣的:(Android,Android进阶)