美文网首页UtilsAndroidAndroid网络请求开源库
Butterknife 8.5.1使用-全面,一定要看😏

Butterknife 8.5.1使用-全面,一定要看😏

作者: 流水潺湲 | 来源:发表于2017-03-08 17:55 被阅读4143次

    GitHub项目源码 https://github.com/JakeWharton/butterknife
    官网 http://jakewharton.github.io/butterknife/

    ButterKnife 简介

    ButterKnife是一个专注于Android系统的View注入框架,可以减少大量的findViewById以及setOnClickListener代码,可视化一键生成。


    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()不能通过注解实现。(其他的有些注解框架可以)


    如何添加依赖

    1)在项目的project 的build.gredle 文件中的dependencies标签下添加。(添加插件)

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

    2)在module的build.gredle 文件中添加(官方是这么写的,目前貌似没有用到)

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

    3)在module的build.gredle 文件中的dependencies标签中添加(导入库的依赖)

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

    不过使用时,只要加1)3)dependencies就可以使用了,2)可以不用添加

    如何使用

    常见使用方法:

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

    public abstract class BaseActivity extends Activity {  
        public abstract int getContentViewId();  
          Unbinder bind;
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(getContentViewId());  
           bin  ButterKnife.bind(this);  
            initAllMembersView(savedInstanceState);  
        }  
      
        protected abstract void initAllMembersView(Bundle savedInstanceState);  
      
        @Override  
        protected void onDestroy() {  
            super.onDestroy();  
            ButterKnife.unbind(this);//解除绑定,官方文档只对fragment做了解绑  
        }  
    }  
    

    2)绑定fragment

    
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Button;
    
    import butterknife.BindView;
    import butterknife.ButterKnife;
    
    public class ButterknifeFragment extends Fragment {
    
        @BindView( R.id.button1 )
        public Button button1 ;
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_butterknife, container, false);
    
            //绑定fragment
            ButterKnife.bind( this , view ) ;
            button1.setText( "I am a button ");
            return view ;
        }
    }
    

    3)绑定view

    • 控件id 注解: @BindView()
     @BindView( R.id.button1 )
        public Button button1 ;
        
        // 注意:button 的修饰类型不能是:private 或者 static 。 否则会报错:错误: @BindView fields must not be private or static. (com.zyj.wifi.ButterknifeActivity.button1)
    
    • 多个控件id 注解: @BindViews()
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.Button;
    import java.util.List;
    import butterknife.BindViews;
    import butterknife.ButterKnife;
    
    public class Main2Activity extends AppCompatActivity {
    
        @BindViews({ R.id.button1  , R.id.button2 ,  R.id.button3 })
        public List<Button> buttonList ;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main2);
    
            ButterKnife.bind(this);
    
            buttonList.get( 0 ).setText( "hello 1 ");
            buttonList.get( 1 ).setText( "hello 2 ");
            buttonList.get( 2 ).setText( "hello 3 ");
        }
    }
    
    

    4)绑定资源

    • @BindString() :绑定string 字符串
    package com.zyj.wifi;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.widget.Button;
    
    import butterknife.BindString;
    import butterknife.BindView;
    import butterknife.ButterKnife;
    
    public class ButterknifeActivity extends AppCompatActivity {
    
        @BindView( R.id.button1 ) //绑定button 控件
        public Button button1 ;
    
        @BindString( R.string.app_name )  //绑定string 字符串
        String meg;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_butterknife);
    
            //绑定activity
            ButterKnife.bind( this ) ;
    
            button1.setText( meg );
        }
    }
    
    
    • @BindArray() : 绑定string里面array数组
    <resources>
        <string name="app_name">WiFi管家</string>
        
        <string-array name="city">
            <item>厦门市</item>
            <item>福州市</item>
            <item>泉州市</item>
            <item>漳州市</item>
            <item>龙岩市</item>
        </string-array>
        
    </resources>
    
    
    
    package com.zyj.wifi;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.widget.Button;
    
    import butterknife.BindArray;
    import butterknife.BindView;
    import butterknife.ButterKnife;
    
    public class ButterknifeActivity extends AppCompatActivity {
    
        @BindView( R.id.button1 ) //绑定button 控件
        public Button button1 ;
    
        @BindArray(R.array.city )  //绑定string里面array数组
        String [] citys ;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_butterknife);
    
            //绑定activity
            ButterKnife.bind( this ) ;
    
            button1.setText( citys[0] );
        }
    }
    
    • @BindBitmap( ) : 绑定Bitmap 资源
    import android.graphics.Bitmap;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.widget.ImageView;
    
    import butterknife.BindBitmap;
    import butterknife.BindView;
    import butterknife.ButterKnife;
    
    public class ButterknifeActivity extends AppCompatActivity {
    
        @BindView( R.id.imageView ) //绑定ImageView 控件
        public ImageView imageView ;
    
        @BindBitmap( R.mipmap.wifi )  //绑定Bitmap 资源
        public Bitmap wifi_bitmap ;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_butterknife);
    
            //绑定activity
            ButterKnife.bind( this ) ;
    
            imageView.setImageBitmap( wifi_bitmap );
        }
    }
    
    • @BindColor( ) : 绑定一个颜色值
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.widget.Button;
    
    import butterknife.BindColor;
    import butterknife.BindView;
    import butterknife.ButterKnife;
    
    public class ButterknifeActivity extends AppCompatActivity {
    
        @BindView( R.id.button1 )  //绑定一个控件
        public Button button1 ;
    
        @BindColor( R.color.colorAccent ) int black ;  //绑定一个颜色值
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_butterknife);
    
            //绑定activity
            ButterKnife.bind( this ) ;
    
            button1.setTextColor(  black );
    
        }
    }
    

    5)Adapter ViewHolder 绑定
    把ViewHolder加一个构造方法,在new ViewHolder的时候把view传递进去

    static class ViewHolder {
        @BindView(R.id.tv_item_test)
        TextView tvItemTest;
        @BindView(R.id.bt_item_test)
        Button btItemTest;
        public ViewHolder(View view) {
            ButterKnife.bind(this, view);
        }
    }
    

    item里面Button控件的点击事件也可以使用注解@OnClick来实现,在适配器里面添加就行,如:

     //item的button的点击事件
        @OnClick(R.id.bt_item_test)
        void onClick(){
            Toast.makeText(context,"点击了按钮",Toast.LENGTH_SHORT).show();
    
        }
    
        static class ViewHolder {
            @BindView(R.id.tv_item_test)
            TextView tvItemTest;
            @BindView(R.id.bt_item_test)
            Button btItemTest;
            public ViewHolder(View view) {
                ButterKnife.bind(this, view);
            }
        }
    

    总体就是:

    public class TestAdapter extends BaseAdapter {  
        private List<String> list;  
        private Context context;  
      
        public TestAdapter(Context context, List<String> list) {  
            this.list = list;  
            this.context = context;  
        }  
      
        @Override  
        public int getCount() {  
            return list==null ? 0 : list.size();  
        }  
      
        @Override  
        public Object getItem(int position) {  
            return list.get(position);  
        }  
      
        @Override  
        public long getItemId(int position) {  
            return position;  
        }  
      
        @Override  
        public View getView(int position, View convertView, ViewGroup parent) {  
            ViewHolder holder;  
            if (convertView == null) {  
                convertView = LayoutInflater.from(context).inflate(R.layout.layout_list_item, null);  
                holder = new ViewHolder(convertView);  
                convertView.setTag(holder);  
            } else {  
                holder = (ViewHolder) convertView.getTag();  
            }  
            holder.textview.setText("item=====" + position);  
            return convertView;  
        }  
      
        static class ViewHolder {  
            @BindView(R.id.hello_world)  
            TextView textview;  
      
            public ViewHolder(View view) {  
                ButterKnife.bind(this, view);  
            }  
        }  
    }  
    

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

    • @OnClick( ) : 绑定控件点击事件

    • @OnLongClick( ) : 绑定控件长按事件

    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.widget.Toast;
    
    import butterknife.ButterKnife;
    import butterknife.OnClick;
    import butterknife.OnLongClick;
    
    public class ButterknifeActivity extends AppCompatActivity {
    
        @OnClick(R.id.button1 )   //给 button1 设置一个点击事件
        public void showToast(){
            Toast.makeText(this, "is a click", Toast.LENGTH_SHORT).show();
        }
    
        @OnLongClick( R.id.button1 )    //给 button1 设置一个长按事件
        public boolean showToast2(){
            Toast.makeText(this, "is a long click", Toast.LENGTH_SHORT).show();
            return true  ;
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_butterknife);
    
            //绑定activity
            ButterKnife.bind( this ) ;
    
        }
    }
    

    总结:

    事件注解

    一共有12个

    名称 作用

    • @OnClick 点击事件
    • @OnCheckedChanged 选中,取消选中
    • @OnEditorAction 软键盘的功能键
    • @OnFocusChange 焦点改变
    • @OnItemClick item被点击(注意这里有坑,如果item里面有Button等这些有点击的控件事件的,需要设置这些控件属性focusable为false)
    • @OnItemLongClick item长按(返回真可以拦截onItemClick)
    • @OnItemSelected item被选择事件
    • @OnLongClick 长按事件
    • @OnPageChange 页面改变事件
    • @OnTextChanged EditText里面的文本变化事件
    • @OnTouch 触摸事件
    • @Optional 选择性注入,如果当前对象不存在,就会抛出一个异常,为了压制这个异常,可以在变量或者方法上加入一下注解,让注入变成选择性的,如果目标View存在,则注入, 不存在,则什么事情都不做=如下代码
    @Optional
    @OnCheckedChanged(R.id.cb_test)
    public void onCheckedChanged(CompoundButton buttonView,boolean isChecked){
        if(isChecked){
            tvTest.setText("被选中了...");
        }else{
            tvTest.setText("被取消了...");
        }
    }
    

    绑定注解

    有11种

    名称 解析

    • @BindViews 绑定多个view id为一个view的list变量
    • @BindView 绑定一个view id为一个view 变量
    • @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;

    ButterKnife更多使用

    1)指定多个id绑定事件
    例如绑定多个Button的onclick事件,在小括号里面加大括号,然后用逗号分割即可。

     @OnClick({R.id.bt_test,R.id.bt_test_two})
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.bt_test:
                    tvTest.setText("按钮1被点击了...");
                    break;
                case R.id.bt_test_two:
                    tvTest.setText("按钮2被点击了...");
                    break;
            }
        }
    

    2) 多个view
    使用BindViews绑定多个

    @BindViews({R.id.tv_test,R.id.tv_test_two,R.id.tv_test_three})
    List<TextView> tvList;
    

    使用Action接口或者Setter接口或者View的Property,可以同时设置多个view的属性

    @BindViews({R.id.tv_test,R.id.tv_test_two,R.id.tv_test_three})
    List<TextView> tvList;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
    
    
        //设置多个view的属性
        //方式1 传递值
        ButterKnife.apply(tvList,ENABLED,false);
        //方式2 指定值
        ButterKnife.apply(tvList,DISABLE);
        //方式3 设置View的Property
        ButterKnife.apply(tvList, View.ALPHA, 0.0f);
    
    }
    
    //Action接口设置属性
    static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {
        @Override public void apply(View view, int index) {
            view.setEnabled(false);
        }
    };
    
    //Setter接口设置属性
    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);
        }
    };
    

    3) 自定义View使用注解事件
    不用指定id,直接注解OnClick

    public class MyButton extends Button {
      @OnClick
      public void onClick() {
      }
    }
    

    4)绑定api

    • 使用Activity为根视图绑定任意对象时,如果你使用类似MVC的设计模式你可以在Activity 调用ButterKnife.bind(this, activity),来绑定Controller。
    • 使用ButterKnife.bind(this)绑定一个view的子节点字段.如果你在子View的布局里或者自定义view的构造方法里 使用了inflate,你可以立刻调用此方法。或者,从XML inflate来的自定义view类型可以在onFinishInflate回调方法中使用它。

    5) 多方法的listener
    例如Spinner的setOnItemSelectedListener,他会回调两个方法:

    mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        }
        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });
    

    所以这时候如果我们需要注解onNothingSelected,需要在注解参数添加一个callback,

    @OnItemSelected(R.id.my_spiner)//默认callback为ITEM_SELECTED
    void onItemSelected(int position) {
        Toast.makeText(this, "position: " + position, Toast.LENGTH_SHORT).show();
    }
    
    @OnItemSelected(value = R.id.my_spiner, callback = OnItemSelected.Callback.NOTHING_SELECTED)
    void onNothingSelected() {
        Toast.makeText(this, "Nothing", Toast.LENGTH_SHORT).show();
    }
    

    注意的是Spinner中只要有数据,默认都会选中第0个数据,所以想进入到onNothingSelected()方法,就需要把Adapter中的数据都清空

    6) 使用findById
    Butter knife仍然包含了findById方法,用于仍需从一个view ,Activity,或者Dialog上 find 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);
    

    7 )代码混淆

    -keep class butterknife.** { *; }
    -dontwarn butterknife.internal.**
    -keep class **$$ViewBinder { *; }
    
    -keepclasseswithmembernames class * {
        @butterknife.* <fields>;
    }
    
    -keepclasseswithmembernames class * {
        @butterknife.* <methods>;
    }
    

    zelezny : Butterknife插件的使用

    使用连接 https://github.com/avast/android-butterknife-zelezny

    • 插件安装
      搜索一下,直接安装即可
    安装完成图
    • 插件的使用
      安装完成插件后,会提示重启AS,重启完后,可以写一个布局并且新建一个代码类测试下。测试的过程中要注意的是,需要将光标移到setContentView(R.layout.acty_login),将光标放到R.layout.acty_login,然后右键Generate就有了。要注意一定要将光标放在R.layout.acty_login上面。
    使用流程

    参照:
    http://blog.csdn.net/niubitianping/article/details/54893571

    相关文章

      网友评论

      • 478e01c27811:可以分享下你的代码themes么
        流水潺湲:@我是一只焦 这个是简书的,我自己也有个,包括日志都好了,也不错,等会打包发你
        478e01c27811:@流水潺湲 是的,在简书看好处都是这个样式,怪好看的
        流水潺湲:@我是一只焦 studio样式吗?
      • 4d60d03a6835:你确定这样能绑定成功???
        4d60d03a6835:@流水潺湲 恩,好的,谢谢幺~
        流水潺湲:@忧桑的汪汪 可以啊,现在最新的版本有变动,参照官方的API
      • 天空匠人:看是看了,就是看不懂,有些东西根本就对不上呀,只能看你玩happy了
        流水潺湲:多看点就懂了,只是一个总结性的,需要自己实际去写才知道,代码都是敲出来的:smile:

      本文标题:Butterknife 8.5.1使用-全面,一定要看😏

      本文链接:https://www.haomeiwen.com/subject/yapbgttx.html