Android Butterknife use summary IOC framework

Introduction:
ButterKnife View is injected into a framework to focus on Android system, used to write a lot findViewById to find the View object, with ButterKnife can easily omit these steps. God is great JakeWharton masterpiece, currently used very widely. The most important point, use ButterKnife basically no loss of performance, because ButterKnife used annotations are not reflected in the running, but create a new class at compile time. Integrate project is especially convenient to use is particularly simple.

Through the study of this article, learn how to use ButterKnife in the project. This article contains the following points:

  • Foreword
    • basic introduction
    • ButterKnife advantage
  • basic configuration
  • ButterKnife registration and binding
    • ButterKnife use the experience and Precautions
    • Activity in the binding ButterKnife
    • In the Fragment Binding ButterKnife
    • Binding ButterKnife in the Adapter
  • The basic use of ButterKnife
    • Bind View
    • Binding Resources
    • Event binding
    • Binding monitor
    • Use findById
    • Setting a plurality of view of properties
    • Precautions
    • More binding annotations
    • More events Notes
  • ButterKnife of code obfuscation
  • Butterknife plug: zelezny
    • Plug-in installation
    • Plug-in uses

ButterKnife Project Address: https://github.com/JakeWharton/butterknife

▲ ButterKnife advantage of:

1, binding and powerful View Click event handler function, simplify the code, improve development efficiency

2, convenient disposal Adapter in the ViewHolder binding problem

3, APP will not affect the efficiency of operation, easy to use configuration

4, the code clear, readable

Basic Configuration
configuration uses ButterKnife in android Studio project

  • Step one: add the following code in the Project's build.gradle:
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        classpath 'com.jakewharton:butterknife-gradle-plugin:8.8.1'  //添加这一行
    }
}
  • Step two: add the following code in the App build.gradle:
apply plugin: 'com.jakewharton.butterknife'
  • dependencies added:
compile 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

Build environment is particularly simple, let's look at how you can use

ButterKnife registration and binding

▲ ButterKnife Reviews and precautions:

1, in the binding Activity class: ButterKnife.bind (this); must be the setContentView (); After binding; bind, and after binding the parent class, subclass do not need to bind.

2, in the non-Activity class: In (eg Fragment, ViewHold) binding: ButterKnife.bind (this, view); this can not be replaced here getActivity ().

3, in the need to do Activity unbundling operation, the operation must be done unbundling Fragment in onDestroyView () in.

4, using the modified method ButterKnife and controls, with private or static can not be modified, otherwise it will error. Error: @BindView fields must not be private or static (com.zyj.wifi.ButterknifeActivity.button1).

5, setContentView () can not be achieved by the annotation. (Some other comments framework can)

6, when using Activity bind any object for the root view, if you use something like MVC design pattern you can call ButterKnife.bind (this, activity) Activity in, to bind Controller.

7, using ButterKnife.bind (this, view) a bindable node field of view. If you or a self-defined view of the construction method in use in child View inflate the layout, you can call this method immediately. Alternatively, the custom XML inflate to view onFinishInflate type can use it in the callback method.

▲ binding ButterKnife in an Activity:

Because every time Binding Activity in Activity in onCreate, it is recommended to write a personal BaseActivity complete the binding, a subclass can inherit. Binding Activity must be after setContentView. Use ButterKnife.bind (this) for binding. code show as below:

public class MainActivity extends AppCompatActivity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定初始化ButterKnife ButterKnife.bind(this); } } 

▲ binding ButterKnife in Fragment in:

Fragment life cycle is different from the activity. When bound in a Fragment onCreateView, the view will onDestroyView set to null. When you call a Fragment bind to bind you, Butter Knife will return an instance of a Unbinder. It calls its unbind method at the appropriate life cycle (onDestroyView) callback carried Fragment unbundling. Use ButterKnife.bind (this, view) for binding. code show as below:

public class ButterknifeFragment extends Fragment{ private Unbinder unbinder; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment, container, false); //返回一个Unbinder值(进行解绑),注意这里的this不能使用getActivity() unbinder = ButterKnife.bind(this, view); return view; } /** * onDestroyView中进行解绑操作 */ @Override public void onDestroyView() { super.onDestroyView(); unbinder.unbind(); } } 

▲ binding ButterKnife in the Adapter:

ViewHolder Adapter used in the ViewHolder adding a constructor, the new ViewHolder when passing in the view. Use ButterKnife.bind (this, view) binding, as follows:

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.testlayout, parent, false); holder = new ViewHolder(view); view.setTag(holder); } holder.name.setText("Donkor"); holder.job.setText("Android"); // etc... return view; } static class ViewHolder { @BindView(R.id.title) TextView name; @BindView(R.id.job) TextView job; public ViewHolder(View view) { ButterKnife.bind(this, view); } } } 

The basic use of ButterKnife

▲ Bind View:

  • Control id Notes: @BindView ()
@BindView( R2.id.button)  
public Button button;   
  • Notes id number of controls within the layout: @BindViews ()
public class MainActivity extends AppCompatActivity { @BindViews({ R2.id.button1, R2.id.button2, R2.id.button3}) public List<Button> buttonList ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); buttonList.get( 0 ).setText( "hello 1 "); buttonList.get( 1 ).setText( "hello 2 "); buttonList.get( 2 ).setText( "hello 3 "); } } 

▲ binding resources:

  • Binding string string: @BindString ()
public class MainActivity extends AppCompatActivity { @BindView(R2.id.button) //绑定button 控件 public Button button ; @BindString(R2.string.app_name) //绑定资源文件中string字符串 String str; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定activity ButterKnife.bind( this ) ; button.setText( str ); } } 
  • Binding string inside the array array: @BindArray ()
<resources>  
    <string name="app_name">城市</string>  

    <string-array name="city"> <item>北京市</item> <item>天津市</item> <item>哈尔滨市</item> <item>大连市</item> <item>香港市</item> </string-array> </resources> ------------------------------------------------------------------------------ public class MainActivity extends AppCompatActivity { @BindView(R2.id.button) //绑定button 控件 public Button button ; @BindString(R2.string.app_name) //绑定资源文件中string字符串 String str; @BindArray(R2.array.city) //绑定string里面array数组 String [] citys ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定activity ButterKnife.bind( this ) ; button.setText(citys[0]); } } 
  • Binding Bitmap resources: @BindBitmap ()
public class MainActivity extends AppCompatActivity { @BindView( R2.id.imageView ) //绑定ImageView 控件 public ImageView imageView ; @BindBitmap( R2.mipmap.bm)//绑定Bitmap 资源 public Bitmap bitmap ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定activity ButterKnife.bind( this ) ; imageView.setImageBitmap(bitmap); } } 
  • Binding a color value: @BindColor ()
public class MainActivity extends AppCompatActivity { @BindView( R2.id.button) //绑定一个控件 public Button button; @BindColor( R2.color.colorAccent ) //具体色值在color文件中 int black ; //绑定一个颜色值 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定activity ButterKnife.bind( this ) ; button.setTextColor( black ); } } 

▲ event binding:

  • Bind the click event:

    • Bound control Click event: @OnClick ()

    • Bound controls Press Event: @OnLongClick ()

public class MainActivity extends AppCompatActivity { @OnClick(R2.id.button1 ) //给 button1 设置一个点击事件 public void showToast(){ Toast.makeText(this, "is a click", Toast.LENGTH_SHORT).show(); } @OnLongClick( R2.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_main); //绑定activity ButterKnife.bind( this ) ; } } 
  • Id specify multiple binding events:
public class MainActivity extends AppCompatActivity { //Tip:当涉及绑定多个id事件时,我们可以使用Android studio的Butterknife //插件zelezny快速自动生成的,之后在下面会有介绍安装插件与使用 @OnClick({R.id.ll_product_name, R.id.ll_product_lilv, R.id.ll_product_qixian, R.id.ll_product_repayment_methods}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.ll_product_name: System.out.print("我是点击事件1"); break; case R.id.ll_product_lilv: System.out.print("我是点击事件2"); break; case R.id.ll_product_qixian: System.out.print("我是点击事件3"); break; case R.id.ll_product_repayment_methods: System.out.print("我是点击事件4"); break; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定activity ButterKnife.bind( this ) ; } } 

As can be seen by the above example click event is no more than R2 with the way, if you have to use the wording of R2 can be a single sequential write, correct wording is as follows:

public class MainActivity extends AppCompatActivity { @OnClick(R2.id.ll_product_name) public void onViewClicked1(View view) { System.out.print("我是点击事件1"); } @OnClick(R2.id.ll_product_lilv) public void onViewClicked2(View view) { System.out.print("我是点击事件2"); } @OnClick(R2.id.ll_product_qixian) public void onViewClicked3(View view) { System.out.print("我是点击事件3"); } @OnClick(R2.id.ll_product_repayment_methods) public void onViewClicked4(View view) { System.out.print("我是点击事件4"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定activity ButterKnife.bind( this ) ; } } 
  • Custom View events using bind

Do not specify the id, direct comment OnClick. Look at the code feel like a similar method to achieve with the click event. It did not actually realize OnClickListener interface. code show as below:

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

▲ binding listen:

  • Listeners can be automatically configured to process
@OnClick(R.id.submit)  
public void submit(View view) { // TODO submit data to server... } 
  • All parameters of listener methods are optional
@OnClick(R.id.submit)  
public void submit() { // TODO submit data to server... } 
  • Custom a particular type, it will automatically be converted
@OnClick(R.id.submit)  
    public void sayHi(Button button) {//看括号内参数的变化就明白了 button.setText("Hello!"); } 
  • Specify multiple id in a single binding for the public event handling. Here, for example click event. Other event listener is also possible.
@OnClick(R.id.submitCode,R.id.submitFile,R.id.submitTest)  
    public void sayHi(Button button) {//多个控件对应公共事件 button.setText("Success!"); } 
  • Custom views can be bound to their own listeners do not specify the ID.
public class FancyButton extends Button { @OnClick public void onClick() { // TODO do something! } } 
  • Listener multi-method annotation

The method of annotations, which corresponds to a plurality of callback listener, may be used to bind to any of them. Each comment has a binding its default callback. Use callback parameter to specify a replacement. To Spinner for example.
Originally Code:

Spinner s=new Spinner(this);  
       //原始方法:Spinner 条目选择监听事件 正常写法  
       s.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){  
           @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { } @Override public void onNothingSelected(AdapterView<?> parent) { } }); 

By way of comment Butter Knife

public class MainActivity extends AppCompatActivity { /*利用注解对Spinner item 作选择监听事件处理方式*/ @OnItemSelected(R.id.my_spiner)//默认callback为ITEM_SELECTED void onItemSelected(int position) { Toast.makeText(this, "position: " + position, Toast.LENGTH_SHORT).show(); } /* * 注解onNothingSelected,需要在注解参数添加一个callback, * 注意的是Spinner中只要有数据,默认都会选中第0个数据,所以想进入到onNothingSelected()方法,就需要把Adapter中的数据都清空 */ @OnItemSelected(value = R.id.my_spiner, callback = OnItemSelected.Callback.NOTHING_SELECTED) void onNothingSelected() { Toast.makeText(this, "Nothing", Toast.LENGTH_SHORT).show(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定activity ButterKnife.bind( this ) ; Spinner s=new Spinner(this); } } 
  • Use @OnCheckedChanged listening

The original method should be: setOnCheckedChangeListener (). Use chestnuts

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RadioGroup android:id="@+id/rg_main" android:layout_width="fill_parent" android:layout_height="48dp" android:layout_alignParentBottom="true" android:background="@color/white" android:orientation="horizontal"> <RadioButton android:id="@+id/rg_home" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="false" android:text="@string/nav_one" /> <RadioButton android:id="@+id/rg_wealth" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="false" android:text="@string/nav_two" /> <RadioButton android:id="@+id/rg_account" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="false" android:text="@string/nav_four" /> </RadioGroup> </LinearLayout> ------------------------------------------------------------------------- @OnCheckedChanged({R.id.rg_home,R.id.rg_wealth,R.id.rg_account}) public void OnCheckedChangeListener(CompoundButton view, boolean ischanged ){ switch (view.getId()) { case R.id.rg_home: if (ischanged){//注意:这里一定要有这个判断,只有对应该id的按钮被点击了,ischanged状态发生改变,才会执行下面的内容 //这里写你的按钮变化状态的UI及相关逻辑 } break; case R.id.rg_wealth: if (ischanged) { //这里写你的按钮变化状态的UI及相关逻辑 } break; case R.id.rg_account: if (ischanged) { //这里写你的按钮变化状态的UI及相关逻辑 } break; default: break; } } 

▲ use findById:

Butter Knife still contains the findById () method, from a view for still, the Activity, or Dialog view when the initialization, and it can be automatically converted types.

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 iv = ButterKnife.findById(view, R.id.iv);  

▲ view of a plurality of set properties:

  • apply()

Role: Allows you to immediately operate on all views list.

  • Action and Setter Interface

Role: Action Setter and simple interface allows to specify the behavior.

public class MainActivity extends AppCompatActivity { @BindViews({R2.id.first_name, R2.id.middle_name, R2.id.last_name}) List<EditText> nameViews; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定activity ButterKnife.bind(this); //设置多个view的属性 //方式1:传递值 ButterKnife.apply(nameViews, DISABLE); //方式2:指定值 ButterKnife.apply(nameViews, ENABLED, false); ////方式3 设置View的Property ButterKnife.apply(nameViews, View.ALPHA, 0.0f);//一个Android属性也可以用于应用的方法。 } /* * Action接口设置属性 */ static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() { @Override public void apply(View view, int index) { view.setEnabled(false);//目的是使多个view都具备此属性 } }; /* * 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);//目的是使多个view都具备此属性,可变boolean值是可以传递的 } }; } 

▲ Caution:

  • ButterKinfe annotation label due to different versions vary.
    Before the label after 8.0.0 8.0.0 Bind became BindView, but after 8.7.0 when binding view, use R2.id.XXX instead of the usual R.id.XXX.

View gitHub specific changes and submit the log:
https://github.com/JakeWharton/butterknife/blob/master/CHANGELOG.md#version-800-2016-04-25

  • By default, @ bind and listener binding is required. If you can not find the target view, will throw an exception.
    To suppress this behavior and create an optional binding, you can add annotations to @Nullable field, or add notes to @Optional method.

Any named @Nullable notes can be used for member variables. We recommend using the android "support-annotations" @Nullable annotation library.

@Nullable  
@BindView(R.id.might_not_be_there)   
TextView mightNotBeThere;  

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

▲ more binding annotations:

@BindView -> bind a view; id is a variable view

@BindViews -> Binding plurality of view; ID list is a view of a variable

@BindArray -> Binding string array inside the array; @BindArray (R.array.city) String [] citys;

@BindBitmap -> bindings graphic assets Bitmap; @BindBitmap (R.mipmap.wifi) Bitmap bitmap;

@BindBool -> bind boolean value

@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 -> Binding float

@BindInt -> int bind

@BindString -> bind a String id as a String variable; @BindString (R.string.app_name) String meg;

▲ more events Notes:

@OnClick -> click event

@OnCheckedChanged -> checked, uncheck

@OnEditorAction -> soft keyboard function keys

@OnFocusChange -> change focus

@OnItemClick item -> clicked (Note that there is a pit, if the item there, which are clicked Button controls these events, we need to set the controls property focusable to false)

@OnItemLongClick item -> Long press (return really can intercept onItemClick)

@OnItemSelected -> item is selected events

@OnLongClick -> Long press event

@OnPageChange -> page change event

@OnTextChanged -> EditText inside the text change event

@OnTouch -> touch events

@Optional -> selective implantation, if the current object does not exist, it will throw an exception, in order to suppress the exception, you can add notes on what variables or methods, so that the injection becomes selective, if the target exists View, the injection does not exist, do nothing

//Test @Optional
@Optional  
@OnCheckedChanged(R.id.cb_test)  
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked){ if(isChecked){ tvTest.setText("被选中..."); }else{ tvTest.setText("被取消..."); } } 

ButterKnife of code obfuscation

In the confusion file, add the following code:

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

Butterknife plug: zelezny

  • Plug-in installed:

Toolbar File find Settings ... or use the shortcut Ctrl + Alt + s point open. Search zelezny download and install the plugin, restart Android Studio

 
image
  • Plug-in uses:

After the installation is complete plug-in, you will be prompted to restart AS, after the restart, you can write a new layout and the next code class test. During the testing process should pay attention to is the need to move the cursor setContentView (R.layout.acty_login), place the cursor R.layout.acty_login, then right-Generate there. Here quoted a gif renderings, more intuitive to show the advantages of plug-in brings. For more need to bind id, save the need to manually code beating time.

 


Author: lisx_
link: https: //www.jianshu.com/p/3678aafdabc7
Source: Jane book
Jane book copyright reserved by the authors, are reproduced in any form, please contact the author to obtain authorization and indicate the source.

Guess you like

Origin www.cnblogs.com/cfas/p/10947358.html