【原创】Android Butterknife 的分析与使用

Android Butterknife 的分析与使用


0. 内容概览

  • 1. 问题背景

  • 2. Butterknife简介

  • 3. Butterknife的使用方法

  • 4. Butterknife的使用范例

  • 4. Butterknife的使用注意事项

  • 5. 总结

  • 6. 参考文档

1. 问题背景

      在项目的开发过程中,发现当前有两个小问题:

  • Activity代码可读性较差;

  • 需要手动填写大量的View绑定,Click事件绑定,ViewHolder事件绑定等,影响开发效率。


 2. Butterknife简介

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

      使用ButterKnife框架可以很好地解决问题上述问题。


3. Butterknife的使用方法

3.1. 本地插件下载

      在settings搜索Zelezny,如下所示:

      

      

3.2. 本地框架搭建

(1) Project的build.gradle中添加依赖

dependencies {
  classpath 'com.android.tools.build:gradle:2.0.0'
  classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 
}

(2) app的build.gradle中增加classpath内容

dependencies {
  compile fileTree(include: ['*.jar'], dir: 'libs')
  compile 'com.jakewharton:butterknife:8.1.0'
  apt 'com.jakewharton:butterknife-compiler:8.1.0'//增加这一句
}

(3) 在Activity基类中进行注解的绑定与解绑,如下:

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

      其他Activity继承至BaseActivity即可正常使用Butterknife插件。

(4) 在Fragment中基类中对Butterknife进行绑定和解绑,如下:

public abstract class BaseFragment extends Fragment {  
    public abstract int getContentViewId();  
    protected Context context;  
    protected View mRootView;  
  
    @Nullable  
    @Override  
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  
        mRootView =inflater.inflate(getContentViewId(),container,false);  
        ButterKnife.bind(this,mRootView);//绑定framgent  
        this.context = getActivity();  
        initAllMembersView(savedInstanceState);  
        return mRootView;  
    }  
  
    protected abstract void initAllMembersView(Bundle savedInstanceState);  
  
    @Override  
    public void onDestroyView() {  
        super.onDestroyView();  
        ButterKnife.unbind(this);//解绑  
    }  
}  

      其他Fragment继承至BaseFragment即可正常使用Butterknife插件。

3.3. 可视化一键生成注解

      对于要进行注解的layout文件,通过快捷键一键添加Butterknife注解,如下所示:

      

      自动补全代码如下:

      

      然后通过注解生成的textView,imageView就可以正常使用了。

3.4. 手动注解

(1) 绑定View(以Button为例):

     @BindView( R.id.button ) private Button button;

(2) 绑定String:

     @BindString( R.string.msg ) private String msg;

(3) 绑定String数组

     @BindArray(R.array.citys ) private String [] citys ;

(4) 绑定Bitmap资源

     @BindBitmap( R.mipmap.wifi ) private Bitmap wifi_bitmap ;

(5) 绑定颜色值

     @BindColor( R.color.black ) private int black ;

(6) 绑定OnClick事件

     @OnClick(R.id.button )

     private void click(){ Toast.makeText(this, "is a click", Toast.LENGTH_SHORT).show(); }

(7) 绑定OnLongClick事件

     @OnLongClick( R.id.button1 ) //给 button1 设置一个长按事件

     private void longClick(){Toast.makeText(this, "is a long click", Toast.LENGTH_SHORT).show();}

其他方法以此类推,所有的绑定注释如下所示:

     


4. Butterknife的使用范例

(1) 一般Activity

     使用前

public class ExampleActivity extends AppCompatActivity {
    private final static String TAG = ExampleActivity.class.getSimpleName();
    String butterKnifeStr;
    Drawable butterKnifeDrawable;
    Button butterKnifeBtn;
    ImageView butterKnifeIv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_butter_knife);
        initResource();
        initViews();
    }

    private void initViews() {
        butterKnifeBtn = (Button) findViewById(R.id.btn_butter_knife);
        butterKnifeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e(TAG, "onButterKnifeBtnClick");
            }
        });
        butterKnifeIv = (ImageView) findViewById(R.id.iv_butter_knife);
        butterKnifeBtn.setText(butterKnifeStr);
        butterKnifeIv.setImageDrawable(butterKnifeDrawable);
    }

    private void initResource() {
        butterKnifeStr = getString(R.string.title_btn_butter_knife);
        butterKnifeDrawable = getDrawable(R.mipmap.ic_launcher);
    }
}

      使用后:

public class ButterKnifeActivity extends AppCompatActivity {
    private final static String TAG = ButterKnifeActivity.class.getSimpleName();
    private Unbinder unbinder;
    @BindString(R.string.title_btn_butter_knife)
    String butterKnifeStr;
    @BindDrawable(R.mipmap.ic_launcher)
    Drawable butterKnifeDrawable;
    @BindView(R.id.btn_butter_knife)
    Button butterKnifeBtn;
    @BindView(R.id.iv_butter_knife)
    ImageView butterKnifeIv;

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

    private void initViews() {
        butterKnifeBtn.setText(butterKnifeStr);
        butterKnifeIv.setImageDrawable(butterKnifeDrawable);
    }

    @OnClick(R.id.btn_butter_knife)
    public void onButterKnifeBtnClick(View view) {
        Log.e(TAG, "onButterKnifeBtnClick");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbinder.unbind();
    }
}

(2) Adapter的使用

     使用前

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.person_item_layout, null);
            holder = new ViewHolder();
            holder.name = (TextView) convertView.findViewById(R.id.name);
            holder.age = (TextView) convertView.findViewById(R.id.age);
            holder.location = (TextView) convertView.findViewById(R.id.location);
            holder.work = (TextView) convertView.findViewById(R.id.work);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        Person person = getItem(position);
        if (null != person) {
            holder.name.setText(person.getName());
            holder.age.setText(String.valueOf(person.getAge()));
            holder.location.setText(person.getLocation());
            holder.work.setText(person.getWork());
        }
 
        return convertView;
    }
 
    static class ViewHolder {
        TextView name;
        TextView age;
        TextView location;
        TextView work;
    }

     使用后

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.person_item_layout, null);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        Person person = getItem(position);
        if (null != person) {
            holder.name.setText(person.getName());
            holder.age.setText(String.valueOf(person.getAge()));
            holder.location.setText(person.getLocation());
            holder.work.setText(person.getWork());
        }
 
        return convertView;
    }
 
    static class ViewHolder {
        @InjectView(R.id.person_name)
        TextView name;
        @InjectView(R.id.person_age)
        TextView age;
        @InjectView(R.id.person_location)
        TextView location;
        @InjectView(R.id.person_work)
        TextView work;
 
        public ViewHolder(View view) {
            ButterKnife.inject(this, view);
        }
    }

      可以发现,使用Butterknife后,不仅可以通过注解节省大量的写代码的时间,而且可以增强代码的可读性。


5. Butterknife的使用注意事项

  • 本地搭建Butterknife框架,通过gralde下载Android studio的相关依赖文件,可以通过链接下载相关jar包等资源文件,并将依赖文件覆盖到C:\Users\(***)\.gradle\caches\modules-2目录下,可以节省更新gradle的时间;

  • Activity或者Fragment中使用ButterKnife,要注意在onCreate中绑定,在onDestroy中解绑,否则可能会造成内存泄漏

  • ButterKnife只能在标注为Application的Module中使用;

  • Activity ButterKnife.bind(this);必须在setContentView();之后,且父类bind绑定后,子类不需要再bind;

  • Fragment ButterKnife.bind(this, mRootView);

  • 属性布局不能用private or static 修饰,否则会报错


5. 总结

      总的来说,ButterKnife有以下几点优势:

    • 兼容之前的使用,所以不会对之前的使用方法造成影响

    • 强大的View绑定和Click事件处理功能,简化代码,提升开发效率

    • 方便的处理Adapter里的ViewHolder绑定问题

    • 运行时不会影响APP效率,使用配置方便

    • 代码清晰,可读性强


6. 参考文献

  • http://jakewharton.github.io/butterknife/

  • http://www.cnblogs.com/zhaoyanjun/p/6016341.html

  • http://www.jianshu.com/p/9ad21e548b69

  • https://github.com/JakeWharton/butterknife

  • http://blog.csdn.net/itjianghuxiaoxiong/article/details/50177549

  • http://www.jianshu.com/p/0392199a682b

  • http://www.cnblogs.com/flyme/p/4517560.html

 

 

posted @ 2017-04-11 20:34  Charles04  阅读(972)  评论(0编辑  收藏  举报