精华内容
参与话题
问答
  • butterknife 使用

    千次阅读 2019-01-06 15:49:29
    ButterKnife是一个专注于Android系统的View注入框架,以前总是要写很多findViewById来找到View对象,有了ButterKnife可以很轻松的省去这些步骤。使用ButterKnife对性能基本没有损失,因为ButterKnife用到的注解并不是...

    介绍
    ButterKnife是一个专注于Android系统的View注入框架,以前总是要写很多findViewById来找到View对象,有了ButterKnife可以很轻松的省去这些步骤。使用ButterKnife对性能基本没有损失,因为ButterKnife用到的注解并不是在运行时反射的,而是在编译的时候生成新的class。


    使用

    1. 在androidstudio上面File->project structure ->app->dependencies->点击加号->选择Library dependency->找到butterknife->点击ok(相信后面大家都会啦)

    2. 安装Android ButterKnife Zelezny插件(这个插件也特别好用)

    我们可以自己下载插件对应的jar包,然后自己安装,当然我们也可以在plugins中Browse repositories搜索ButterKnife Zelezny来安装,这里我们使用第一种方法安装这个插件。网站是https://plugins.jetbrains.com/plugin/7369-android-butterknife-zelezny下载成功后。

    点击上方图片对应的Install plugin from disk来找到这个插件的jar文件安装目录点击ok进行安装。

    3. 使用

    在setContentView(R.layout.activity_main);后面将这个布局注入当前的Activity(),语句是ButterKnife.inject(this);注意一定要在setContentView(R.layout.activity_main)后面,不同的版本语句也会不一样,我的是5.1.1有的语句是ButterKnife.Bind(this),但是用法都是一样的。

    在Activity中先选中对应的布局右键会出现Generate找到我们的插件,左键便成功初始化了控件,以后再也不用findViewByid()啦,哈哈。。(当然还有很多用法,这只是其中一个)

    
     

     

     

     

     

     

     

     

    展开全文
  • 史上最全的android中Butterknife的使用 提示: 博主:章飞 _906285288的博客 博客地址:http://blog.csdn.net/qq_29924041 Butterknife是什么?   是由国外一个大牛开源出来的一个项目,是为了用过...

    史上最全的android中Butterknife的使用


    提示:
    博主:章飞 _906285288的博客
    博客地址:http://blog.csdn.net/qq_29924041


    Butterknife是什么?

      是由国外一个大牛开源出来的一个项目,是为了用过注解的形式来在android中绑定view以及事件信息。 目前在github上面的开源地址为
    https://github.com/JakeWharton/butterknife
    有兴趣的可以看看


    Butterknife的好处

    1. 强大的View绑定事件和资源文件的绑定
    2. 使用的便捷性上,剔除了原始绑定时候的复杂性
    3. 由于大多数的注解都是在编译期,所以不会影响程序运行的效率
    4. 代码清晰,可读性相对来说要强很多

    怎么使用Butterknife?

    插件的添加和库的依赖

    插件的添加

        File -> Settings -> Plugins -> 搜索ButterKnife,找到Android ButterKnife Zeleany进行安装重启AndroidStudio 
    

    这里写图片描述

    库的依赖

    如果想要去使用Butterknife,肯定是要去进行库的依赖的吧
        compile 'com.jakewharton:butterknife:8.8.1'
        annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    

    认识Butterknife的注解类型

    Butterknife最新的版本中,为我们提供了总共有25个注解。其中分成两类,一个是资源的绑定形式,另外一种就是事件监听的类型

    绑定注解,视图,资源,等等,一共13个
    名称 解析
    @BindViews 绑定多个view id 为一个view的list变量 @BindViews({ R.id.first_name, R.id.middle_name, R.id.last_name }) List<EditText> nameViews;
    @BindView 绑定一个view id为一个view变量@BindView(R.id.title) TextView title;
    @BindArray 绑定String中的array数组 @BindArray(R.array.city)String[] citys;
    @BindBitmap 绑定图片资源文件, @BindBitmap(R.mipmap.wifi) Bitmap bitmap;
    @BindBool 绑定真假boolean @BindBool(R.bool.boor)
    @BindColor 绑定颜色 @BindColor(R.color.red)
    @BindDimen 绑定尺寸 @BindDimen(R.dimen.spacer) Float spacer;
    @BindDrawable 绑定Drawable @BindDrawable(R.drawable.graphic) Drawable graphic
    @BindFloat 绑定Float
    @BindInt 绑定Int
    @BindString 绑定一个String id为String变量, @BindString(R.string.app_name) String msg
    @BindAnim 绑定动画
    @BindFont 绑定字体文字
    绑定事件,一共有12个事件监听
    名称 解析
    @OnClick 点击事件
    @OnCheckedChanged 选中,选中取消
    @OnEditorAction 软键盘的功能按键
    @OnFocusChange 焦点改变
    @OnItemClick Item被点击事件(注意这里有坑,如果item里面有Button等这些有点击的控件事件的,需要设置这些控件属性focusable为false)
    @OnItemLongClick tem长按,返回真则可以拦截onItemClick
    @OnItemSelected Item被选择事件
    @OnLongClick 长按事件
    @OnPageChange 页面改变事件
    @OnTextChanged EditText里面的文本变化事件
    @OnTouch 触摸事件
    @Optional 选择性注入,如果当前对象不存在,就会抛出一个异常,为了压制这个异常,可以在变量或者方法上加入一下注解,让注入变成选择性的,如果目标View存在,则注入, 不存在,则什么事情都不做=如下代码
    ButterKnife在Activity中的使用方式
    数据绑定标签13个,Bind系列

    @BindAnim
    使用方式如下所示:

    @BindAnim(R.anim.fade_in) Animation fadeIn;
    

    @BindArray
    使用方式如下所示:
    由于数组资源文件中的数组可以定义成多种数据类型,因此使用方式如下所示

    1:String array
        //数组:
        <string-array name="countries">
            <item>中国</item>
            <item>日本</item>
    </string-array>
        @BindArray(R.array.countries) String[] countries;
    2:Int array
        //数组:
        <integer-array name="phones">
            <item>12345</item>
            <item>43534</item>
        </integer-array>
        @BindArray(R.array.phones) int [] phones
    3:Text array
        //数组:与stringArray类似
        <string-array name="countries">
            <item>中国</item>
            <item>日本</item>
        </string-array>
        @BindArray(R.array.options) CharSequence[] options;
    
    4:Type array ----->android.content.res.TypeArray
        //数组,TypeArray中是一种混合类型形式,所以相对比较复杂一点:
        <string-array name="feed_icons">
            <item>@color/colorAccent</item>
            <item>@dimen/dp_72</item>
            <item>@drawable/leak_canary_icon</item>
            <item>@drawable/flashligth_drawable_btn</item>
            <item>@drawable/ic_launcher_background</item>
            <item>@layout/encode</item>
        </string-array>
        @BindArray(R.array.icons) TypedArray icons;
    

    @BindBitmap
    绑定图片操作

    @BindBitmap(R.drawable.logo) Bitmap logo;
    @BindBitmap(R.mipmap.ic_launcher) Bitmap mBitmap;

    @BindBool
    绑定boolean类型的值

    //首先要在资源文件中定义bool,
    <bool name="isRun" >true</bool>
    
    @BindBool(R.bool.isRun) Boolean isRun;
    //不过一般情况下是不这样进行使用的

    @BindColor
    绑定颜色的操作,同样颜色可以绑定一个单一的颜色,同样也可以绑定颜色的组合形式,

    //绑定单一颜色:
    //定义颜色类型:
    <color name="colorAccent">#FF4081</color>
    @BindColor(R.color. colorAccent) int colorAccent;
    
    //绑定颜色组合:使用ColorStateList类进行操作,定义一个button_view的selector
    <?xml version="1.0" encoding="utf-8"?>  
    <selector xmlns:android="http://schemas.android.com/apk/res/android">  
                <item android:state_pressed="true"  
              android:color="#ffff0000"/> <!-- pressed -->  
            <item android:state_focused="true"  
              android:color="#ff0000ff"/> <!-- focused -->  
                <item android:color="#ff000000"/> <!-- default -->  
    </selector>
    
    //这样就可以绑定ColorStateList,然后通过空间的setTextColor进行设置
    @BindColor(R.color. button_view) ColorStateList greenSelector

    @BindDimen

    绑定尺寸,尺寸有int类型和float类型

    @BindDimen(R.dimen.sp_20) int gapxp;
    @BindDimen(R.dimen.sp_20) float gapsp;
    

    @BindDrawable
    Drawable的绑定

    @BindDrawable(R.drawable.placeholder) Drawable placeholder
    //还有另外一种形式,即drawable与attr共同使用,attr为特性,tint为着色的意思
    @BindDrawable(value = R.drawable.placeholder, tint = R.attr.colorAccent) 
    Drawable tintedPlaceholder;

    @BindFloat 绑定float类型

    <item name="whatever" format="float" type="dimen">1.1</item>
    <item name="twelve_point_two" format="float" type="dimen">12.2</item>
        BindFloat(R.dimen.image_ratio) float imageRatio
    BindFloat(R.dimen. twelve_point_two) float twelve_point_two
    

    @BindFont
    绑定的是字体样式

    BindFont(R.font.comic_sans) Typeface comicSans;
    通过setTypeFace的形式进行设置样式
    

    @BindInt
    绑定int类型

    BindInt(R.int.columns) int columns;

    @BindString
    绑定String类型的资源

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

    @BindView
    将控件的id与视图进行绑定操作

    @BindView(R.id.showArrayText)  TextView mView;

    @BindViews

    BindViews其实是BindView的一种扩展形式,主要适用于有多个相同的view的时候,这个时候可以使用BindViews将其装装载在一个集合/数组中,这样在使用的时候,直接通过下标的形式进行使用
    
    BindViews({ R.id.title, R.id.subtitle }) List<TextView> titlesList;
    BindViews({ R.id.title, R.id.subtitle }) TextView [] titlesArray;
    //然后通过titlesList.get(1)或者titlesArray [1]来进行获取
    
    事件触发注解标签的使用形式,12个On系列

    @ OnCheckedChanged
    这个属性主要是针对类似RadioButton,CheckedBox,其父类为CompoudButton类型的控件
    主要可以有以下三种形式:注意:函数名字其实是可以随机取值的,只是形式参数有两种形式

    //第一种:形式参数中只有一个boolean
    @OnCheckedChanged(R.id.checkBox)
        void onChecked(boolean isChecked){
            Toast.makeText(this, "checkBox:"+isChecked, Toast.LENGTH_SHORT).show();
    }
    
    //第二种:形式参数中有控件CompoundButton和boolean
    @OnCheckedChanged(R.id.checkBox2)
    void onCheckedChanged(CompoundButton compoundButton,boolean isChecked){
            Toast.makeText(this, "compoundButton111:"+compoundButton+"\tcheckBox:"+isChecked, Toast.LENGTH_SHORT).show();
    }
    
    //第三种形式为ID具有两个,这个时候如果没有视图绑定,默认是会进行绑定操作的
    @OnCheckedChanged({R.id.checkBox3,R.id.checkBox4})
    void onCheckedChanged2(CompoundButton compoundButton,boolean isChecked){
            Toast.makeText(this, "compoundButton2222:"+compoundButton+"\tcheckBox:"+isChecked, Toast.LENGTH_SHORT).show();
    }
    

    @ OnClick
    OnClick很简单,其实也就是点击事件,只是在ButterKnife中点击事件中的参数可以没有,也可以有一个View类型,,没有绑定View,也可以生效

    @OnClick(R.id.example) 
        void onClick() {
            Toast.makeText(this, "Clicked!", Toast.LENGTH_SHORT).show();
        }
    
    @OnClick({R.id.topText,R.id.bottom_text})
        void onTextViewClick(View mView){
            Toast.makeText(BufferKnifeDemoActicity.this,((TextView)mView).getText().toString(),Toast.LENGTH_LONG).show();
    }
    
    //如果是在自定义view中,类似,这个时候,就不用指定具体的ID了。
    Class customBtn extends Button{
            @Onclick
            public void onClick(View view){
        }
    }

    @ OnEditorAction
    OnEditorAction主要是针对EditText来说的,需要注意的是 setOnEditorActionListener这个方法,并不是在我们点击EditText的时候触发,也不是在我们对EditText进行编辑时触发,而是在我们编辑完之后点击软键盘上的回车键才会触发
    因为EditText是继承自TextView,因此在实际过程中,也是可以有TextView返回的

    @OnEditorAction(R.id.example) boolean onEditorAction(KeyEvent key) {
        Toast.makeText(this, "Pressed: " + key, Toast.LENGTH_SHORT).show();
        return true;
     }
    
    @OnEditorAction(R.id.example) boolean onEditorAction(TextView mTextView,int actionId,KeyEvent key) {
        Toast.makeText(this, "Pressed: " + key, Toast.LENGTH_SHORT).show();
        return true;
     }
    
    //其具体使用的方式可以参考OnEditorActionListener的使用

    @ OnFocusChange

    此注解主要是来源于setOnFocusChangeListener,即其主要的作用同样也是针对EditText来进行使用的

    @OnFocusChange(R.id.example) void onFocusChanged(boolean focused) {
            Toast.makeText(this, focused?"Gainedfocus": "Lost focus", Toast.LENGTH_SHORT).show();
      }
    
    //同时还有一种两个参数是的函数形式
    @OnFocusChange(R.id.example) void onFocusChanged(View mView,boolean focused) {
            Toast.makeText(this, focused?"Gainedfocus": "Lost focus", Toast.LENGTH_SHORT).show();
     }
    

    @ OnItemClick
    这个注解主要是针对AdapterView,即类似ListView这样的控件使用的事件类型,貌似在实际RecycleView不是继承与AdapterView,因此不能使用此注解

    //第一种形式:参数只有一个position
        @OnItemClick(R.id.example_list) void onItemClick(int position) {
            Toast.makeText(this, "Clicked position " + position + "!", Toast.LENGTH_SHORT).show();
      }
    
    //第二种形式:参数有四个
        @OnItemClick(R.id.example_list) void onItemClick(AdapterView mView,View itemView,int position,long num) {
            Toast.makeText(this, "Clicked position " + position + "!", Toast.LENGTH_SHORT).show();
      }

    @ OnItemLongClick
    这个注解主要是针对AdapterView,即类似ListView这样的控件使用的事件类型,貌似在实际RecycleView不是继承与AdapterView,因此不能使用此注解

    //第一种形式:参数只有一个position
        @ OnItemLongClick (R.id.example_list) void onItemClick(int position) {
            Toast.makeText(this, "Clicked position " + position + "!", Toast.LENGTH_SHORT).show();
      }
    
    //第二种形式:参数有四个
        @OnItemLongClick(R.id.example_list) 
    void onItemClick(AdapterView mView,View itemView,int position,long num) {
            Toast.makeText(this, "Clicked position " + position + "!", Toast.LENGTH_SHORT).show();
      }
    

    @ OnItemSelected
    针对的控件也是AdapterView的子类,即ListView以及Spinner这一类,这个注释的使用与OnItemSelectedListener的使用方式类似

    @OnItemSelected(R.id.example_list) void onItemSelected(int position) {
                Toast.makeText(this, "Selected position " + position + "!", Toast.LENGTH_SHORT).show();
        }
    
    
    @OnItemSelected(R.id.example_list) void onItemSelected(android.widget.AdapterView view, android.view.View mview, int position, long id) {
                Toast.makeText(this, "Selected position " + position + "!", Toast.LENGTH_SHORT).show();
        }
    
    
    @OnItemSelected(value = R.id.example_list, callback = NOTHING_SELECTED)
        void onNothingSelected() {
            Toast.makeText(this, "Nothing selected!", Toast.LENGTH_SHORT).show();
        }
    

    @ OnLongClick
    OnLongClick很简单,其实也就是点击事件,只是在ButterKnife中点击事件中的参数可以没有,也可以有一个View类型,,没有绑定View,也可以生效

    @OnLongClick (R.id.example) 
        void onClick() {
            Toast.makeText(this, " OnLongClick!", Toast.LENGTH_SHORT).show();
        }
    
    @OnLongClick ({R.id.topText,R.id.bottom_text})
        void onTextViewClick(View mView){
            Toast.makeText(BufferKnifeDemoActicity.this,((TextView)mView).getText().toString(),Toast.LENGTH_LONG).show();
    }
    

    @ OnPageChange
    OnPageChange注解主要是针对ViewPager来进行实现的,ViewPager中有OnPageChangeListener啊

    
    //使用方式一:
    OnPageChange(R.id.example_pager) void onPageSelected(int position) {
      Toast.makeText(this, "Selected " + position + "!", Toast.LENGTH_SHORT).show();
    }
    
    //使用方式二:
    @OnPageChange(value = R.id.example_pager, callback = PAGE_SCROLL_STATE_CHANGED)
    void onPageStateChanged(int state) {
        Toast.makeText(this, "State changed: " + state + "!", Toast.LENGTH_SHORT).show();
    }
    
    //使用方式三:
    @OnPageChange(value = R.id.example_pager, callback = PAGE_SCROLLED)
    void onPageScrolled (int position, float positionOffset, int positionOffsetPixels) {
    
    }
    //主要是通过枚举类型,PAGE_SCROLLED,PAGE_SCROLL_STATE_CHANGED,PAGE_SELECTED来进行判断使用的
    

    @ OnTextChanged
    主要是针对TextWatcher控件来进行实现的。

    //使用方式一:
    @OnTextChanged(R.id.example) void onTextChanged(CharSequence text) {
        Toast.makeText(this, "Text changed: " + text, Toast.LENGTH_SHORT).show();
    }
    
    //使用方式二:
    @OnTextChanged(value = R.id.example, callback = BEFORE_TEXT_CHANGED)
    void onBeforeTextChanged(CharSequence text) {
       Toast.makeText(this, "Before text changed: " + text, Toast.LENGTH_SHORT).show();
     }
    
    //使用方式三:
    @OnTextChanged(value = R.id.example, callback = AFTER_TEXT_CHANGED )
    void onAfterTextChange(Editable editable) {
       Toast.makeText(this, "after text changed: " + text, Toast.LENGTH_SHORT).show();
     }
    //与OnPagerChange使用类似,其也是用过枚举变量来进行控制的,BEFORE_TEXT_CHANGED,TEXT_CHANGED,AFTER_TEXT_CHANGED

    @ OnTouch
    针对所有的View都有的onTouch事件来进行设计的,只要是View的子类都可以使用此注解

    //使用方式一:
        @OnTouch(R.id.example) boolean onTouch() {
                Toast.makeText(this, "Touched!", Toast.LENGTH_SHORT).show();
                return false;
        }
    //使用方式二,带参数类型
        @OnTouch(R.id.example) boolean onTouch(View mView,MotionEvent event) {
                Toast.makeText(this, "Touched!", Toast.LENGTH_SHORT).show();
                return false;
        }
    //注意点:
        //OnTouch为了与系统的onTouch进行匹配上,即满足事件传递的要求,所以其是有返回值的,也就要求没和函数都是要有返回值。
    

    @ Optional
    默认情况下,@Bind 和listener的注入都是必须的,如果target view没有被发现,则会报错. 为了抑制这种行为,可以用@Optional注解来标记field和方法,让注入变成选择性的,如果targetView存在,则注入, 不存在,则什么事情都不做.或者使用 Android’s “support-annotations” library.中的@Nullable来修饰

    @Optional @OnClick(R.id.subtitle) void onSubtitleClick() {}
    ButterKnife的findById

    ButterKnife 也提供了findById函数,通过findById()可以获取Activity、Dialog、View中的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);
    不过以上的一个方法其实已经过时了,官方其实不再建议去使用这几个方法了

    ButterKnife.apply()函数
    函数类型:

    在ButterKnife这个类中关于apply方法的重载数量高达到12条,由此可以看出来,apply这个函数的重要性。但是这个函数使用来干嘛的撒???
    ButterKnife中的apply()函数对view集合元素或者单个view的Action, Setter和Property进行修改。
    要想知道的方式,必须首先看一下它的函数类型参数类型吧:如以下所示:

    @UiThread @SafeVarargs 
    1:public static <T extends View> void apply(@NonNull List<T> list, @NonNull Action<? super T>... actions)
    
    @UiThread @SafeVarargs 
    2:public static <T extends View> void apply(@NonNull T[] array, @NonNull Action<? super T>... actions)
    
    @UiThread
    3:public static <T extends View> void apply(@NonNull List<T> list,@NonNull Action<? super T> action)
    
    @UiThread
    4:public static <T extends View> void apply(@NonNull T[] array, @NonNull Action<? super T> action)
    
    @UiThread
    5:public static <T extends View> void apply(@NonNull List<T> list,@NonNull Action<? super T> action)
    
    6:
    @UiThread @SafeVarargs 
    public static <T extends View> void apply(@NonNull T view,@NonNull Action<? super T>... actions)
    
    7:
    @UiThread
    public static <T extends View> void apply(@NonNull T view, @NonNull Action<? super T> action)
    
    8: 
    @UiThread
    public static <T extends View, V> void apply(@NonNull List<T> list,@NonNull Setter<? super T, V> setter, V value)
    
    9:
    @UiThread
    public static <T extends View, V> void apply(@NonNull T[] array,@NonNull Setter<? super T, V> setter, V value)
    
    10: 
    @UiThread
    public static <T extends View, V> void apply(@NonNull T view,@NonNull Setter<? super T, V> setter, V value)
    
    11: 
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) // http://b.android.com/213630
    @RequiresApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    @UiThread
    public static <T extends View, V> void apply(@NonNull List<T> list,@NonNull Property<? super T, V> setter, V value)
    
    12     
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) // http://b.android.com/213630
    @RequiresApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    @UiThread
    public static <T extends View, V> void apply(@NonNull T[] array,@NonNull Property<? super T, V> setter, V value)
    
    参数解释:

    所有的函数其实都围绕三个参数类型来的:

    1:泛型类型为View子类的类型或者泛型数组或者泛型集合,可以参数可以认为是绑定的View类型
    2:Action类型的接口和Setter类型的接口

    public interface Action<T extends View> {
        /** Apply the action on the {@code view} which is at {@code index} in the list.*/
            @UiThread
            void apply(@NonNull T view, int index);
      }
    
    /** A setter that can apply a value to a list of views. */
    public interface Setter<T extends View, V> {
        /** Set the {@code value} on the {@code view} which is at {@code index} in the list. */
        @UiThread
         void set(@NonNull T view, V value, int index);
      }
    

    其实Action接口主要是为了对View或者Views进行管理操作,而Setter接口其实就是对view或者views的属性或者值进行操作管理

    使用案例:
    使用方式一:
    //1:绑定View
      @Bind({ R.id.first_name, R.id.middle_name, R.id.last_name })  
      List<EditText> nameViews; 
    
    //2:定义Action或者Setter的实现接口类型
      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);  
      }  
    };
    
    //3:对views调用apply,修改views中每个view类型属性
    ButterKnife.apply(nameViews, DISABLE);  
    ButterKnife.apply(nameViews, ENABLED, false);
    
    使用方式二:
        对于系统的相关属性可以直接系统默认的属性常量进行设置
        ButterKnife.apply(nameViews, View.ALPHA, 0.0f);
    

    代码混淆方式

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

    以上就是关于
    ButterKnife的使用,如果对你的学习有帮助的话,点个关注撒。后续从源码角度分析这种绑定的机制

    欢迎持续访问博客:https://blog.csdn.net/qq_29924041

    展开全文
  • ButterKnife使用方法详解

    万次阅读 热门讨论 2018-06-04 23:09:14
    ButterKnife是一个专注于Android系统的View注入框架,以前总是要写很多findViewById来找到View对象,有了ButterKnife可以很轻松的省去这些步骤。使用ButterKnife对性能基本没有损失,因为ButterKnife用到的注解并不是...

    介绍

    ButterKnife是一个专注于Android系统的View注入框架,以前总是要写很多findViewById来找到View对象,有了ButterKnife可以很轻松的省去这些步骤。使用ButterKnife对性能基本没有损失,因为ButterKnife用到的注解并不是在运行时反射的,而是在编译的时候生成新的class。

    GitHub地址:https://github.com/JakeWharton/butterknife

    原理

    利用了IOC的(Inverse of Controll)控制反转结构,2004年后改名为DI(dependency injection)依赖注入。目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性。越来越趋向于后端开发了。

    配置

    在Android Studio项目中配置使用ButterKnife
    本文介绍使用的as版本为3.1.2,ButterKnife版本为8.8.1
    1.如果你是直接在app中使用,只需在app的 build.gradle 中添加如下代码:

    dependencies {
      implementation 'com.jakewharton:butterknife:8.8.1'
      annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    }

    2.如果你是在Library库中使用,按照github上的配置来写,会报错。

    Unable to find method 'com.android.build.gradle.api.BaseVariant.getOutputs()Ljava/util/List;'.
    Possible causes for this unexpected error include:<ul><li>Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
    Re-download dependencies and sync project (requires network)</li><li>The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem.
    Stop Gradle build processes (requires restart)</li><li>Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project.</li></ul>In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.

    在网上找到了大神的解决办法解决组件化开发butterknife 在 library中使用的坑
    第一步
    配置项目根目录的build.gradle
    这里写图片描述
    这里注意butterknife的版本,我从8.8.1一直往下降,到了8.5.1才可以使用

    第二步
    配置library中的build.gradle
    顶部添加插件apply plugin: ‘com.jakewharton.butterknife’
    这里写图片描述
    在dependencies中添加和在app中的一样
    这里写图片描述
    到此配置已完成,下面说下在library中使用时注意事项

    1.用R2代替R,这点butterknife的开发者也做了说明

    @BindView(R2.id.test_tv)
    TextView tv;
    @BindView(R2.id.test_btn)
    Button btn;

    2.onclick事件,在library中不能用switch,如果使用,点击事件会失效,用if和else代替。还要注意id的使用
    这里写图片描述

    安装插件

    这里写图片描述
    安装后重启生效
    使用时,右键layout->点击Generate->Generate ButterKnife Injections
    这里写图片描述
    这里写图片描述

    注解使用用例

    绑定id:BindView

    @BindView(R.id.login_btn_login)
    Button btn_login;

    Adapter中ViewHolder使用,注意:是this

    public MyViewHolder(View itemView){
            super(itemView);
            ButterKnife.bind(this, itemView);
    }

    Button点击事件:@OnClick

    @OnClick({R.id.login_btn_login})
    public void onViewClicked(View view) {
            switch (view.getId()) {
                case R.id.login_btn_login:
    
                    break;
                default:
                    break;
            }
        }

    CheckBox点击事件:@OnCheckedChanged

    @OnCheckedChanged({R.id.login_cb_remember_password, R.id.login_cb_auto_login})
    public void onViewCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
            switch (compoundButton.getId()) {
                case R.id.login_cb_remember_password:
                    if (isChecked) {
    
                    } else {
    
                    }
                    break;
                case R.id.login_cb_auto_login:
                    if (isChecked) {
    
                    } else {
    
                    }
                    break;
            }
        }

    RadioButton点击事件:@OnClick

    @OnClick({R.id.rb_man, R.id.rb_woman})
    public void onViewCheckedChanged(RadioButton radioButton) {
            boolean checked = radioButton.isChecked();
            switch (radioButton.getId()) {
                case R.id.rb_man:
                    if (checked) {
    
                    }
                    break;
                case R.id.rb_woman:
                    if (checked) {
    
                    }
                    break;
            }
        }

    ViewPager事件监听:@OnPageChange

    @OnPageChange(R.id.viewpager)
    public void onPageSelected(int position) {
            switch (position) {
                case 0:
    
                    break;
                case 1:
    
                    break;
            }
        }

    Demo下载地址:ButterKnifeDemo

    展开全文
  • ButterKnife使用详解

    万次阅读 2017-03-23 19:40:19
    ButterKnife是控件注入框架,可以帮助安卓开发者省去初始化控件的重复性工作,简单快捷地初始化布局文件中的控件,极大地提升开发效率。 项目地址-传送门。 导入ButterKnife至项目中 1.在工程的build.gradle中...

    前言

    ButterKnife是控件注入框架,可以帮助安卓开发者省去初始化控件的重复性工作,简单快捷地初始化布局文件中的控件,极大地提升开发效率。
    项目地址-传送门

    导入ButterKnife至项目中

    在项目的build.gradle中添加依赖,然后同步项目,即可下载butterknife库至项目中

    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
    
        implementation 'com.android.support:appcompat-v7:25.2.0'
    
        //加入下面这两行代码
        implementation 'com.jakewharton:butterknife:8.8.1'
        annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    
    }

    简单使用butterknife初始化控件

    1.创建一个android工程,布局如下
    这里写图片描述

    2.在activity中的oncreate()方法里初始化butterknife框架
    注意初始化要放在setView()之后

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

    3.查找TextView与Button

    public class ButterKnifeTestActivity extends AppCompatActivity {
        //绑定控件,省去了写findviewbyid的重复性操作
        @BindView(R.id.tv_test1)
        private TextView tvTest;
        @BindView(R.id.btn_test1)
        private Button btnTest;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_butter_knife_test);
            ButterKnife.bind(this);
        }
    }

    4.测试控件是否被正确初始化

      tvTest.setText("文本控件已被初始化");
      btnTest.setText("按钮被初始化");

    运行工程,结果如下,报了一个编译错误。
    这里写图片描述

    Error:(14, 22) 错误: @BindView fields must not be private or static. (com.example.hapzhu.andrioddemotest.ButterKnifeTestActivity.tvTest)

    意思是控件不能被声明为私有的或者是静态的,看来butterknife框架是对控件声明有限制的,将private去掉即可。

        @BindView(R.id.tv_test1)
       TextView tvTest;
        @BindView(R.id.btn_test1)
        Button btnTest;

    这里写图片描述

    5.给按钮设置点击监听事件

    @OnClick(R.id.btn_test1)
        public void onclick(View view){
            btnTest.setText("我被点击了");
            tvTest.setText("天若有情天亦老");
        }

    随便写一个方法,参数可以放View也可以不放任何参数,
    在方法上一行注解OnClick即可绑定点击事件,注意该方法必须不能为private或者是static的,与声明时规则一致。
    这里写图片描述

    下载注解插件进行一键初始化

    打开android的plugins中心,搜索butterknife
    这里写图片描述
    点击browse repo,下载前两个插件都可以。
    这里写图片描述
    下载完成后,回到activity代码的setContentview处,右键布局文件名,注意一定要把光标停在布局文件名上
    这里写图片描述
    选择Generate,这时可以看到生成butterknife注解的选项,如果光标不放在布局文件名上,则看不到该选项。
    这里写图片描述
    点击生成butterknife注解
    这里写图片描述
    插件将布局文件中的所有id都加载出来了,还可以设置点击事件,点击confirm即可快速初始化控件,非常方便。

       @BindView(R.id.tv_test1)
        TextView tvTest1;
        @BindView(R.id.btn_test1)
        Button btnTest1;
        @BindView(R.id.et_test1)
        EditText etTest1;
        @BindView(R.id.lv_test1)
        ListView lvTest1;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_butter_knife_test);
            ButterKnife.bind(this);
            tvTest1.setText("文本控件已被初始化");
            btnTest1.setText("按钮被初始化");
    
        }
    
    
        @OnClick(R.id.btn_test1)
        public void onViewClicked() {
            btnTest1.setText("我被点击了");
            tvTest1.setText("天若有情天亦老");
        }

    效果与手动注解一样,对于安卓开发工作者来说,这个插件确实是个神器,节省了大量初始化控件的时间。

    其它用途绑定

    绑定res里资源对象

    class ExampleActivity extends Activity {
        //绑定字符串
      @BindString(R.string.title) String title;
      //绑定图形
      @BindDrawable(R.drawable.graphic) Drawable graphic;
      //绑定颜色
      @BindColor(R.color.red) int red; // int or ColorStateList field
      //绑定长度
      @BindDimen(R.dimen.spacer) Float spacer; // int (for pixel size) or float (for exact value) field
      // ...
    }

    绑定Fragment

    public class FancyFragment extends Fragment {
      @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fancy_fragment, container, false);
        ButterKnife.bind(this, view);
        // TODO Use fields...
        return view;
      }
    }

    绑定adapter

    public class MyAdapter extends BaseAdapter {
      @Override public View getView(int position, View view, ViewGroup parent) {
        ViewHolder holder;
        if (view != null) {
          holder = (ViewHolder) view.getTag();
        } else {
          view = inflater.inflate(R.layout.whatever, parent, false);
          //利用构造器将item的view传入viewHolder中
          holder = new ViewHolder(view);
          view.setTag(holder);
        }
    
        holder.name.setText("John Doe");
        // etc...
    
        return view;
      }
    
      static class ViewHolder {
        @BindView(R.id.title) TextView name;
        @BindView(R.id.job_title) TextView jobTitle;
    
        public ViewHolder(View view) {
        //在构造器中绑定view
          ButterKnife.bind(this, view);
        }
      }
    }

    绑定控件ID直接将控件添加至集合或数组中

    @BindViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
    //nameViews的集中中添加了三个edittext对象
    List<EditText> nameViews;

    一次性改变集合中所有对象的值-apply

    
    //Action and Setter interfaces allow specifying simple behavior.
    
    //初始化DISABLE
    static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {
      @Override public void apply(View view, int index) {
      //将view设为不可输入
        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);
      }
    };
    //DISABLE与ENABLED是上述接口的实现类,表示统一设置view集合的对应属性
    ButterKnife.apply(nameViews, DISABLE);
    ButterKnife.apply(nameViews, ENABLED, false);
    //如果是view的自带属性,可以不用实现接口,直接使用
    ButterKnife.apply(nameViews, View.ALPHA, 0.0f);
    

    绑定listview的item点击事件

    @OnItemSelected(R.id.list_view)
    void onItemSelected(int position) {
      // TODO ...
    }

    findviewById的简化

    适用于从dialog中找到控件

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

    2018/04/03更新注意事项

    在Android Studio 3.0以上,依赖的控件是butter knife 8.5.1以上版本都会报这个错
    需要将classpath 'com.jakewharton:butterknife-gradle-plugin:8.5.1'
    这个控件的依赖降到8.5.1

    Unable to find method 'com.android.build.gradle.api.BaseVariant.getOutputs()Ljava/util/List;'.
    Possible causes for this unexpected error include:<ul><li>Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
    Re-download dependencies and sync project (requires network)</li><li>The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem.
    Stop Gradle build processes (requires restart)</li><li>Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project.</li></ul>In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.

    2018/07/28更新:as 3.1及以上,butterknife 8.8.1报错解决方案

    在Android studio 3.1及以上版本中,butterknife又是最新版的8.8.1,构建时老是报错。针对此异常,查看了很多解决方法,没想到最后解决方案竟然是这么简单。
    只需要将build中的引用的butteknife注释插件去掉,然后将app.build的butterknife依赖跟注解依赖改成最新的8.8.1即可解决构建异常问题,并且功能正常使用。
    实际上是我之前所写的引入butterknife插件的那两步是只针对于组件中的library的,并不是主module,所以会出现构建异常,如果是主module只需要添加依赖即可了,这确实是我误导了别人,深感抱歉,现在我将前面的内容给移到这里来了。
    下述步骤为组件library中使用butterknife插件的方法。
    1.在library工程的build.gradle中导入butterknife插件
    这里写图片描述

    
    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:2.3.0'
            //加入下面这段代码
            classpath 'com.jakewharton:butterknife-gradle-plugin:8.5.1'
        }
    }
    
    allprojects {
        repositories {
            jcenter()
        }
    }
    
    
    

    2.在项目的build.gradle中添加butterknife的插件,即是app中的builde.gradle
    这里写图片描述

    //引用的library表示这是一个组件,而非主module(application)
    apply plugin: 'com.android.library'
    //加入下面这段代码
    apply plugin: 'com.jakewharton.butterknife'

    3.使用R2代替R来查找资源id

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

    之前在主module中添加了butterknifte插件并构建异常的解决方案。

    第一步:

    
    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:2.3.0'
            //删除前文中所说在工程的build.gradle中引入的插件
            //classpath 'com.jakewharton:butterknife-gradle-plugin:8.5.1'
        }
    }
    
    allprojects {
        repositories {
            jcenter()
        }
    }
    
    
    

    第二步

    apply plugin: 'com.android.application'
    //在app.build删除下面这段代码
    //apply plugin: 'com.jakewharton.butterknife'

    第三步

    将butterknife的依赖改为下述代码

    implementation 'com.jakewharton:butterknife:8.8.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

    demo项目地址

    展开全文
  • ButterKnife(已过时)

    2019-04-23 09:29:14
    在Activity中绑定 :ButterKnife.bind(this)必须在setContentView之后绑定,且父类bind绑定后,子类不需要再bind public class MainActivity extends AppCompatActivity { @Override protected void on...
  • ButterKnife入门教程

    千次阅读 2018-07-16 09:04:42
    版权所有,转载请注明出处... 目录 1. ButterKnife 2. ButterKnife是什么,看一下Github上作者JakeWharton大神的介绍 3. AndroidStudio集成ButterKnife插件和依赖 3.1 插件集成 3.2 添加依赖 4 开始使用 4.1 1...
  • 1.Butterknife是干什么的? 2.我们如何去看Butterknife框架 3.如果我们自己写一个类似Butterknife框架,我们如何去做?   ButterKnife是一个专注于Android系统的View注入框架,可以减少大量的findViewById 以及 ...
  • ButterKnife9.0的使用

    千次阅读 2019-05-15 11:17:17
    随着Androidstudio升级到了3.4.0,在使用ButterKnife8.8.6的时候报错,提示要升级,后来看了一下,发现ButterKnife竟然已经升级到了10真是厉害,但是我用了一下ButterKnife10发现报错。原因如下图所示...
  • 配置 1.在project的builde.gradel 中 dependencies { classpath 'com.android.tools.build:gradle:2.1.2' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'//...} ...2.在module的builde.gradel 中...
  • 浅谈Android ButterKnife框架的使用

    万次阅读 2019-05-28 15:15:45
    浅谈Android ButterKnife框架的使用 一、简介 ​ ButterKnife 是注解中相对简单易懂的很不错的开源框架,是一个 专注于Android系统的View注入框架, 以前总是要写很多findViewById来找到View对象,有了ButterKnife...
  • ButterKnife介绍

    2020-04-10 21:51:49
    ButterKnife介绍 ButterKnife是一个专注于Android系统的View注入框架,以前总是要写很多findViewById来找到View对象,有了ButterKnife可以很轻松的省去这些步骤。是大神JakeWharton的力作,目前使用很广。最重要的...
  • Android Butterknife(黄油刀) 使用方法总结

    万次阅读 多人点赞 2017-09-07 12:53:40
    ButterKnife是一个专注于Android系统的View注入框架,以前总是要写很多findViewById来找到View对象,有了ButterKnife可以很轻松的省去这些步骤。是大神JakeWharton的力作,目前使用很广。最重要的一点,使用Butter...
  • ButterKnife

    2020-07-28 17:39:41
    ButterKnife是一个专注于Android系统的View注入框架,以前总是要写很多findViewById来找到View对象,有了ButterKnife可以很轻松的省去这些步骤。使用ButterKnife对性能基本没有损失,因为ButterKnife用到的注解并不是...
  • Android Studio中ButterKnife使用 ButterKnife是大神JakeWharton开源的View依赖注入框架, 使用注解就可以完成View的查找,简化了代码的书写。 告别传统的findViewById()的方式去查找控件, 这样不仅...
  • 离开外包公司后,也开始接触... 以下是针对ButteKnife 8.4.0的一些安装及使用。 (一)添加依赖: 当然也可以自行去下载相应的jar包,个人更喜欢直接添加依赖,简单一点。 compile 'com.jakewharton:butterkni...
  • 刚接手的成熟项目,维护熟悉中,发现新建的Activity,点住setContentView处右键Generate快捷生成ButterKnife注解的入口竟然没有,已经集成好了呀,后来搜索发现插件没安装,安装一下就可以了: File->Setting->...
  • 正文: 这里给大家提供一下butterknife的jar包下载,直接copy到libs包下,添加到项目中就好了。点击打开链接 这里我们就按Android studio 的案例来演示一下。 第一
  • 前言:当我们在Activity或Fragment要引用layout布局下的控件的时候,一般做法是findViewById(R.id.XXX) 当你布局文件...这个时候使用Butterknife插件就可以很好的解决这些问题,什么事情都想着让程序自动化帮忙减轻工
  • 参考视频:http://ke.atguigu.com/course/140 开源地址:https://github.com/JakeWharton/butterknife 参考文章:... 一.Butter Knife简介 ...ButterKnife是目前常用的一
  • Android Butterknife使用

    2018-09-21 10:34:11
    在参考学长写的项目的时候,看见了这个 butterKnife 框架。想到当初他们有推荐过,目前也确实需要,所以就边学边用了。参考Android Butter Knife 框架——最好用的View注入和官方文档。本人英语较渣,欢迎有余力的...

空空如也

1 2 3 4 5 ... 20
收藏数 23,942
精华内容 9,576
关键字:

butterknife