黄油刀

    xiaoxiao2025-09-02  230

    【攻克Android (34)】Butter Knife 黄油刀

    博客分类:  攻克Android系列   本文围绕以下四个部分展开:  一、注解式框架  二、Butter Knife  案例一  案例二:用 ListView 展示一个列表数据,每个Item里含有一个Button,可以点击。  一、注解式框架           1. 注解式开发:           JDK 1.5后支持注解方式。想用注解式开发,就要自定义注解。           @Override就是一种自带的注解。很多框架都采用注解方式来实现。           当追求更高的开发效率,用更简洁的代码、更清晰的代码逻辑来进行高效的开发的时候,使用注解式框架开发可简化代码,提升开发效率和代码的可读性。           2. 主流注解式框架:           (1)AndroidAnnotations           配置麻烦,需要在功能清单文件中注册生成的子类。反射机制会占用资源内存,且耗时。           (2)Dagger           采用预编译技术,高效。但是对View绑定操作注解不是很方便。           (3)Butter Knife           它是View 及事件等依赖注入框架。使用方便,配置简单,有强大的View注入绑定和简单的常用方法注解。  二、Butter Knife           它是View 及事件等依赖注入框架。           1. 特点:           (1)强大的View注入绑定和Click事件的处理。简化代码,提升开发效率。           (2)可以方便地处理ListView的Adapter里的ViewHolder绑定问题。           (3)运行时不会影响App效率,使用配置方便。           (4)代码思路清晰,可读性强。           2. 用法:           导包:           compile 'com.jakewharton:butterknife:6.0.0'           在当前 Activity(this)的onCreate中注册(注入黄油刀):  Java代码   ButterKnife.inject(this);            (1)View绑定(绑定控件):           Activity声明绑定控件:  Java代码   @InjectView(R.id.tvTitle)    TextView tvTitle;            黄油刀注入控件,相当于:先声明变量,然后通过 findViewById(R.id.tvCompany) 初始化变量。黄油刀直接帮我们绑定好了控件:           InjectView: Bind a field to the view for the specified ID. The view will automatically be cast to the field type.  Java代码   @InjectView(R.id.tvTitle) // 相当于 通过 findViewById(R.id.tvCompany) 初始化变量。   TextView tvTitle; // 相当于 声明变量:private TextView tvCompany;            注意:不同写为:private TextView tvTitle;  会报错:@InjectView fields must not be private or static.           (2)Onclick等事件处理:  Java代码   @OnClick(R.id.btnHello)   public void sayHi(){       Toast.makeText(this,"你好!",Toast.LENGTH_SHORT).show();   }            (3)ListView的Adapter里的ViewHolder绑定问题。  案例一           1. strings.xml。字符串。  Xml代码   <resources>       <string name="app_name">ButterKnifeDemo</string>          <string name="hello_world">Hello world!</string>       <string name="action_settings">Settings</string>          <string name="btn_good_night">Good Night!</string>       <string name="btn_play">播放</string>       <string name="btn_stop">停止</string>       <string name="btn_view_holder">ViewHolder</string>   </resources>            2. activity_main.xml。布局  Xml代码   <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"       xmlns:tools="http://schemas.android.com/tools"       android:layout_width="match_parent"       android:layout_height="match_parent"       android:paddingBottom="@dimen/activity_vertical_margin"       android:paddingLeft="@dimen/activity_horizontal_margin"       android:paddingRight="@dimen/activity_horizontal_margin"       android:paddingTop="@dimen/activity_vertical_margin"       tools:context=".MainActivity">          <Button           android:id="@+id/btnHello"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:text="@string/hello_world"/>          <Button           android:id="@+id/btnGoodNight"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:layout_below="@id/btnHello"           android:text="@string/btn_good_night"/>          <Button           android:id="@+id/btnPlay"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:layout_below="@id/btnGoodNight"           android:text="@string/btn_play"/>          <Button           android:id="@+id/btnStop"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:layout_below="@id/btnPlay"           android:text="@string/btn_stop"/>          <Button           android:id="@+id/btnViewHolder"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:layout_below="@id/btnStop"           android:text="@string/btn_view_holder"/>      </RelativeLayout>            3. MainActivity。View绑定和Onclick事件处理  Java代码   package com.android.butterknifedemo;      import android.app.Activity;   import android.os.Bundle;   import android.view.Menu;   import android.view.MenuItem;   import android.view.View;   import android.widget.Button;   import android.widget.Toast;      import butterknife.ButterKnife;   import butterknife.InjectView;   import butterknife.OnClick;   import butterknife.Optional;         public class MainActivity extends Activity {          // 2. Actitvity里声明绑定控件       // @Optional:加入后,若此id不存在,则程序不会崩溃,而是抛出异常       @Optional@InjectView(R.id.btnHello)       Button buttonHello;       @InjectView(R.id.btnPlay)       Button buttonPlay;       @InjectView(R.id.btnStop)       Button buttonStop;          @Override       protected void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);           setContentView(R.layout.activity_main);              // 1. onCreate() 方法里注册 ButterKnife           ButterKnife.inject(this);       }          // 3. 注入 View 事件,不带参数       @OnClick(R.id.btnHello)       public void sayHi(){           Toast.makeText(this,"你好!",Toast.LENGTH_SHORT).show();       }          // 4. 注入 View 事件,带参数       @OnClick(R.id.btnGoodNight)       public void sayGoodNight(Button btnGoodNight){           btnGoodNight.setText("晚上好!");       }          // 5. 同时注入多个 View 事件       @OnClick({R.id.btnPlay,R.id.btnStop})       public void playMusic(View view){           switch (view.getId()){               case R.id.btnPlay:                   Toast.makeText(this,"播放音乐",Toast.LENGTH_SHORT).show();                   break;               case R.id.btnStop:                   Toast.makeText(this,"停止播放",Toast.LENGTH_SHORT).show();           }       }             // ----------------------------------------------------------       @Override       public boolean onCreateOptionsMenu(Menu menu) {           // Inflate the menu; this adds items to the action bar if it is present.           getMenuInflater().inflate(R.menu.menu_main, menu);           return true;       }          @Override       public boolean onOptionsItemSelected(MenuItem item) {           // Handle action bar item clicks here. The action bar will           // automatically handle clicks on the Home/Up button, so long           // as you specify a parent activity in AndroidManifest.xml.           int id = item.getItemId();              //noinspection SimplifiableIfStatement           if (id == R.id.action_settings) {               return true;           }              return super.onOptionsItemSelected(item);       }   }            4. MyAdapter。处理ListView的Adapter里的ViewHolder绑定问题。  Java代码   package com.android.butterknifedemo;      import android.content.Context;   import android.view.LayoutInflater;   import android.view.View;   import android.view.ViewGroup;   import android.widget.BaseAdapter;   import android.widget.Button;   import android.widget.TextView;      import butterknife.ButterKnife;   import butterknife.InjectView;      /**   * 在 ViewHolder 模式中注入   */   // 1. 继承自 BaseAdapter   public class MyAdapter extends BaseAdapter{       // 4. 定义上下文       private Context mContext;          /**       * 5. 构造方法       * @param context       */       public MyAdapter(Context context) {           // 上下文通过构造方法传过来           mContext = context;       }          @Override       public int getCount() {           return 0;       }          @Override       public Object getItem(int position) {           return position;       }          @Override       public long getItemId(int position) {           return 0;       }          @Override       public View getView(int position, View convertView, ViewGroup parent) {           // 3. 声明 holder 为空           ViewHolder holder = null;              // 6.           if(holder==null){               // 重新载入布局               convertView = LayoutInflater.from(mContext).inflate(                       R.layout.activity_main,parent,false);               // 对 holder 进行实例化               holder = new ViewHolder(convertView);               // 获得按钮控件               holder.btnViewHolder = (Button) convertView.findViewById(R.id.btnViewHolder);               // 设置标签               convertView.setTag(holder);           } else {               holder = (ViewHolder) convertView.getTag();           }           // 7.           holder.btnViewHolder.setText("更改");           return convertView;       }          // 2. 写一个 结构持有者 类       static class ViewHolder{           @InjectView(R.id.btnViewHolder)           Button btnViewHolder;              public ViewHolder(View view){               ButterKnife.inject(this,view);           }       }   }   案例二:用 ListView 展示一个列表数据,每个Item里含有一个Button,可以点击。           1. activity_main.xml。布局:一个ListView。  Xml代码   <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"       xmlns:tools="http://schemas.android.com/tools"       android:layout_width="match_parent"       android:layout_height="match_parent"       android:paddingBottom="@dimen/activity_vertical_margin"       android:paddingLeft="@dimen/activity_horizontal_margin"       android:paddingRight="@dimen/activity_horizontal_margin"       android:paddingTop="@dimen/activity_vertical_margin"       tools:context=".MainActivity">          <ListView           android:id="@+id/listView"           android:layout_width="match_parent"           android:layout_height="match_parent"/>      </RelativeLayout>            2. item.xml。每一个ListView的项。包括一个文本和一个按钮  Xml代码   <?xml version="1.0" encoding="utf-8"?>   <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"       android:layout_width="match_parent"       android:layout_height="match_parent"       android:descendantFocusability="blocksDescendants"       android:orientation="vertical">          <TextView           android:id="@+id/tvText"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:text="@string/app_name" />          <Button           android:id="@+id/btn"           android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:layout_toRightOf="@id/tvText" />      </RelativeLayout>            注:ListView中出现button等可以拦截点击事件的控件的时候,要加属性:  Xml代码   android:descendantFocusability="blocksDesendants"            3. MyAdapter。自定义适配器。  Java代码   package com.android.bufferknifedemo;      import android.content.Context;   import android.view.View;   import android.view.ViewGroup;   import android.widget.BaseAdapter;   import android.widget.Button;   import android.widget.TextView;   import android.widget.Toast;      import java.util.ArrayList;      import butterknife.ButterKnife;   import butterknife.InjectView;      /**   * Created by Xiangdong on 2015/7/12.   */   public class MyAdapter extends BaseAdapter {       Context mContext;       private ArrayList<String> lists;          public MyAdapter(Context context, ArrayList<String> list) {           mContext = context;           lists = list;       }          @Override       public int getCount() {           return lists.size();       }          @Override       public Object getItem(int position) {           return lists.get(position);       }          @Override       public long getItemId(int position) {           return position;       }          @Override       public View getView(int position, View convertView, ViewGroup parent) {           ViewHolder holder = null;           if (convertView == null) {               convertView = View.inflate(mContext, R.layout.item, null);               holder = new ViewHolder(convertView);               convertView.setTag(holder);           } else {               holder = (ViewHolder) convertView.getTag();           }              String s = lists.get(position);           holder.tvText.setText(s);           holder.btn.setOnClickListener(new View.OnClickListener() {               @Override               public void onClick(View v) {                   Toast.makeText(mContext, "点击", Toast.LENGTH_SHORT).show();               }           });           return convertView;       }          static class ViewHolder {           // 绑定控件           @InjectView(R.id.tvText)           TextView tvText;           @InjectView(R.id.btn)           Button btn;              public ViewHolder(View view) {               ButterKnife.inject(this, view);           }       }   }            4. MainActivity。  Java代码   package com.android.bufferknifedemo;      import android.app.Activity;   import android.os.Bundle;   import android.view.Menu;   import android.view.MenuItem;   import android.widget.ListView;   import android.widget.Toast;      import java.util.ArrayList;      import butterknife.ButterKnife;   import butterknife.InjectView;   import butterknife.OnItemClick;      public class MainActivity extends Activity {       @InjectView(R.id.listView)       ListView listView;       private MyAdapter adapter;       private ArrayList<String> list;          @Override       protected void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);           setContentView(R.layout.activity_main);              ButterKnife.inject(this);              list = new ArrayList<>();           list.add("测试1");           list.add("测试2");           list.add("测试3");           list.add("测试4");           list.add("测试5");           list.add("测试6");           list.add("测试7");           list.add("测试8");           list.add("测试9");           adapter = new MyAdapter(this, list);           listView.setAdapter(adapter);       }          @OnItemClick(R.id.listView)       public void onMyItemClick(int position) {           Toast.makeText(this"位置:" + position, Toast.LENGTH_SHORT).show();       }          // ------------------------------------------------------------------       @Override       public boolean onCreateOptionsMenu(Menu menu) {           // Inflate the menu; this adds items to the action bar if it is present.           getMenuInflater().inflate(R.menu.menu_main, menu);           return true;       }          @Override       public boolean onOptionsItemSelected(MenuItem item) {           // Handle action bar item clicks here. The action bar will           // automatically handle clicks on the Home/Up button, so long           // as you specify a parent activity in AndroidManifest.xml.           int id = item.getItemId();              //noinspection SimplifiableIfStatement           if (id == R.id.action_settings) {               return true;           }              return super.onOptionsItemSelected(item);       }   }  
    转载请注明原文地址: https://ju.6miu.com/read-1302238.html
    最新回复(0)