Annotative Framework--The Use of Butterknife

Keywords: ButterKnife Fragment Android github

Write in front: This document uses version 7.0, version 8.0 method name has been changed, it is recommended to see the official document, the overall business logic and principles have not changed. Official website

In the process of android programming, we will write a lot of layout and click events. Simple and repetitive operations like initial view and view monitor make people feel troublesome, so we can use annotations to implement them. ButterKnife is a relatively simple and easy-to-understand open source framework in annotations, while online documents and examples are out of date. Version changes after 7.0 Very big, the previous annotations can not be used, so draw on the official documents to summarize, and then introduce how to use. Basically refer to the official documents, plus their own experience.


ButterKnife Advantages:

1. Powerful View Binding and Click Event Processing Function, Simplify Code, Improve Development Efficiency

2. Handling ViewHolder Binding in Adapter Conveniently

3. Runtime will not affect the efficiency of APP, easy to use and configure.

4. Clear code and readability


Use experience:

1.Activity ButterKnife.bind(this); must be set ContentView (); and after the parent bind is bound, the subclass does not need to bind any more.

2.Fragment ButterKnife.bind(this, mRootView);

3. Attribute layout cannot be modified with private or static, otherwise error will be reported.

4.setContentView() cannot be implemented through annotations. (Other annotation frameworks can)


Official websitehttp://jakewharton.github.io/butterknife/

Use steps:

Import the ButterKnife jar package:

1) If you are Eclipse, you can download the jar package from the official website.
2) If you are Android Studio, you can search butterknife directly by File - > Project Structure - > Dependencies - > Library dependency. The first one is
3) Of course, you can also configure it with maven and gradle

  1. MAVEN  
  2.     <dependency>  
  3.       <groupId>com.jakewharton</groupId>  
  4.       <artifactId>butterknife</artifactId>  
  5.       <version>(insert latest version)</version>  
  6.     </dependency>  
  7.   
  8. GRADLE  
  9. compile 'com.jakewharton:butterknife:(insert latest version)'  
  10.   
  11. Be sure to suppress this lint warning in your build.gradle.(Close)  
  12. lintOptions {  
  13.   disable 'InvalidPackage'  
  14. }  


Note that if you use it in a Library project, follow the following steps (described in github) or you cannot find view:


Note: Official website and github There are also corresponding reference steps.


2. Common usage methods:
1) Since onCreate binds Activity in Activity every time, I suggest writing a BaseActivity to complete the binding and inherit subclasses.
Note: ButterKnife.bind(this); binding Activity must be after setContentView:
The implementation is as follows (as in the FragmentActivity implementation):

  1. public abstract class BaseActivity extends Activity {  
  2.     public abstract int getContentViewId();  
  3.   
  4.     @Override  
  5.     protected void onCreate(Bundle savedInstanceState) {  
  6.         super.onCreate(savedInstanceState);  
  7.         setContentView(getContentViewId());  
  8.         ButterKnife.bind(this);  
  9.         initAllMembersView(savedInstanceState);  
  10.     }  
  11.   
  12.     protected abstract void initAllMembersView(Bundle savedInstanceState);  
  13.   
  14.     @Override  
  15.     protected void onDestroy() {  
  16.         super.onDestroy();  
  17.         ButterKnife.unbind(this);//Unbound. Official documents only unbind fragment s  
  18.     }  
  19. }  

2) Binding fragment

  1. public abstract class BaseFragment extends Fragment {  
  2.     public abstract int getContentViewId();  
  3.     protected Context context;  
  4.     protected View mRootView;  
  5.   
  6.     @Nullable  
  7.     @Override  
  8.     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  
  9.         mRootView =inflater.inflate(getContentViewId(),container,false);  
  10.         ButterKnife.bind(this,mRootView);//Binding Framegent  
  11.         this.context = getActivity();  
  12.         initAllMembersView(savedInstanceState);  
  13.         return mRootView;  
  14.     }  
  15.   
  16.     protected abstract void initAllMembersView(Bundle savedInstanceState);  
  17.   
  18.     @Override  
  19.     public void onDestroyView() {  
  20.         super.onDestroyView();  
  21.         ButterKnife.unbind(this);//Untying  
  22.     }  
  23. }  

3) Binding view

  1. @Bind(R.id.hello_world)  
  2. TextView mHelloWorldTextView;  
  3. @Bind(R.id.app_name)  
  4. TextView mAppNameTextView;//view  

4) Binding resources

  1. @BindString(R.string.app_name)  
  2. String appName;//sting  
  3. @BindColor(R.color.red)  
  4. int textColor;//colour  
  5. @BindDrawable(R.mipmap.ic_launcher)  
  6. Drawable drawable;//drawble  
  7. @Bind(R.id.imageview)  
  8. ImageView mImageView;  
  9. @Bind(R.id.checkbox)  
  10. CheckBox mCheckBox;  
  11. @BindDrawable(R.drawable.selector_image)  
  12. Drawable selector;  

5) Adapter ViewHolder binding

  1. public class TestAdapter extends BaseAdapter {  
  2.     private List<String> list;  
  3.     private Context context;  
  4.   
  5.     public TestAdapter(Context context, List<String> list) {  
  6.         this.list = list;  
  7.         this.context = context;  
  8.     }  
  9.   
  10.     @Override  
  11.     public int getCount() {  
  12.         return list==null ? 0 : list.size();  
  13.     }  
  14.   
  15.     @Override  
  16.     public Object getItem(int position) {  
  17.         return list.get(position);  
  18.     }  
  19.   
  20.     @Override  
  21.     public long getItemId(int position) {  
  22.         return position;  
  23.     }  
  24.   
  25.     @Override  
  26.     public View getView(int position, View convertView, ViewGroup parent) {  
  27.         ViewHolder holder;  
  28.         if (convertView == null) {  
  29.             convertView = LayoutInflater.from(context).inflate(R.layout.layout_list_item, null);  
  30.             holder = new ViewHolder(convertView);  
  31.             convertView.setTag(holder);  
  32.         } else {  
  33.             holder = (ViewHolder) convertView.getTag();  
  34.         }  
  35.         holder.textview.setText("item=====" + position);  
  36.         return convertView;  
  37.     }  
  38.   
  39.     static class ViewHolder {  
  40.         @Bind(R.id.hello_world)  
  41.         TextView textview;  
  42.   
  43.         public ViewHolder(View view) {  
  44.             ButterKnife.bind(this, view);  
  45.         }  
  46.     }  
  47. }  

 

6) Binding of click events: Click events can be bound without declaring view and without setOnClickLisener ().

A. Direct binding of a method

  1. @OnClick(R.id.submit)  
  2. public void submit(View view) {  
  3.   // TODO submit data to server...  
  4. }  

b. The parameters of all listening methods are optional

  1. @OnClick(R.id.submit)  
  2. public void submit() {  
  3.   // TODO submit data to server...  
  4. }  

c. Define a specific type that will be automatically converted

  1. @OnClick(R.id.submit)  
  2. public void sayHi(Button button) {  
  3.   button.setText("Hello!");  
  4. }  

d. Multiple view s handle the same click event in a unified way, which is convenient and avoids the trouble of repeated invocation of extraction methods.

  1. @OnClick({ R.id.door1, R.id.door2, R.id.door3 })  
  2. public void pickDoor(DoorView door) {  
  3.   if (door.hasPrizeBehind()) {  
  4.     Toast.makeText(this"You win!", LENGTH_SHORT).show();  
  5.   } else {  
  6.     Toast.makeText(this"Try again", LENGTH_SHORT).show();  
  7.   }  
  8. }  

e. Custom view can bind its own listener without specifying id

  1. public class FancyButton extends Button {  
  2.   @OnClick  
  3.   public void onClick() {  
  4.     // TODO do something!  
  5.   }  
  6. }  

f. Add an addTextChangedListener to EditText (that is, the use of multiple callbacks to listen for) and use the specified callbacks to implement the method you want to call back. Which annotation will be used without peer-in to see the annotations on the source code?

  1. @OnTextChanged(value = R.id.mobileEditText, callback = OnTextChanged.Callback.BEFORE_TEXT_CHANGED)  
  2. void beforeTextChanged(CharSequence s, int start, int count, int after) {  
  3.   
  4. }  
  5. @OnTextChanged(value = R.id.mobileEditText, callback = OnTextChanged.Callback.TEXT_CHANGED)  
  6. void onTextChanged(CharSequence s, int start, int before, int count) {  
  7.   
  8. }  
  9. @OnTextChanged(value = R.id.mobileEditText, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)  
  10. void afterTextChanged(Editable s) {  
  11.   
  12. }  


7) Unify a set of View s

A. Load a list

  1. @Bind({ R.id.first_name, R.id.middle_name, R.id.last_name })  
  2. List<EditText> nameViews;  

b. Setting up unified processing

  1. static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {  
  2.   @Override public void apply(View view, int index) {  
  3.     view.setEnabled(false);  
  4.   }  
  5. };  
  6. static final ButterKnife.Setter<View, Boolean> ENABLED = new ButterKnife.Setter<View, Boolean>() {  
  7.   @Override public void set(View view, Boolean value, int index) {  
  8.     view.setEnabled(value);  
  9.   }  
  10. };  

c. Unified Operational Processing, e.g. Setting Points, Attributes, etc.

  1. ButterKnife.apply(nameViews, DISABLE);  
  2. ButterKnife.apply(nameViews, ENABLED, false);  

8) Optional binding: By default, "binding" and "listening" binding are required. If the target view cannot be found, an exception is thrown. So do short processing

  1. @Nullable @Bind(R.id.might_not_be_there) TextView mightNotBeThere;  
  2.   
  3. @Nullable @OnClick(R.id.maybe_missing) void onMaybeMissingClicked() {  
  4.   // TODO ...  
  5. }  

3. Code obfuscation

  1. -keep class butterknife.** { *; }  
  2. -dontwarn butterknife.internal.**  
  3. -keep class **$$ViewBinder { *; }  
  4.   
  5. -keepclasseswithmembernames class * {  
  6.     @butterknife.* <fields>;  
  7. }  
  8.   
  9. -keepclasseswithmembernames class * {  
  10.     @butterknife.* <methods>;  
  11. }  

IV. The Use of Zelezny Plug-ins

In Android Studio - > File - > Settings - > Plugins - > Search for Zelezny download add line, you can quickly generate the corresponding component instance object, without manual writing. When used, on the layout resource code to import annotated Activity or Fragment or ViewHolder, right-click --> Generate -- Generate ButterKnife Injections, and then a selection box appears as shown in the figure. (This dynamic chart is from the official website)



Posted by Dev on Tue, 21 May 2019 12:47:51 -0700