目录
[build.gradle添加 ButterKnife 依赖:](#build.gradle添加 ButterKnife 依赖:)
[MainActivity :](#MainActivity :)
[MyFragment :](#MyFragment :)
[MainActivity :](#MainActivity :)
[MyAdapter :](#MyAdapter :)
[五、 ButterKnife使用的注意事项](#五、 ButterKnife使用的注意事项)
一、ButterKnife介绍
ButterKnife 是一个由 Jake Wharton 开发的 Android 视图绑定框架。它通过使用注解来简化 Android 中的视图绑定操作,减少了手动编写繁琐的 findViewById() 代码的工作量。
二、ButterKnife优点:
**1. 减少冗余代码:**使用 ButterKnife 可以显著减少 Android 项目中的冗余代码。传统上,需要手动编写大量的 findViewById() 代码来查找和绑定视图元素,而 ButterKnife 使用注解方式进行视图绑定,使得代码更加简洁和易读。
2. 提高开发效率:通过自动化视图绑定过程,ButterKnife 可以节省开发人员在开发过程中的时间和精力。它简化了视图绑定的操作,减少了手动编写模板代码的工作量,从而加快了开发速度。
**3. 降低出错风险:**由于 ButterKnife 自动处理视图绑定,减少了手动编写 findViewById() 的过程,因此减少了出错的可能性。通过使用 ButterKnife,可以避免因为繁琐的视图绑定导致的空指针异常或其他错误。
**4. 支持多种绑定类型:**除了常规的视图绑定之外,ButterKnife 还提供了各种注解,可以方便地绑定字符串、颜色、数组等资源,进一步简化了对资源的访问和使用。
**5. 易于扩展和定制:**ButterKnife 具有灵活的架构,可以通过自定义注解和自定义绑定逻辑来扩展和定制其功能。开发人员可以根据项目的需求,自定义注解处理器或实现 ButterKnife 的 Binder 接口,以满足特定的绑定需求。
总的来说,ButterKnife 提供了一种简洁、高效、易用的方式来进行 Android 视图绑定,降低了开发的复杂性,并提高了开发效率和代码质量。它已经成为广大 Android 开发者喜爱的工具之一。
三、ButterKnife的使用
build.gradle添加 ButterKnife 依赖:
java
dependencies {
implementation 'com.jakewharton:butterknife:10.2.3' // 添加此依赖
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3' // 添加此规则
}
1、视图绑定:
ButterKnife 可以通过在代码中使用注解**@BindView**来自动绑定布局文件中的视图元素,无需手动调用 findViewById() 方法。使用 @BindView
注解可以将视图元素直接与代码中的变量进行绑定。
java
@BindView(R.id.textView)
TextView textView;
2、点击事件绑定:
通过使用 @OnClick
和**@OnLongClick( )**注解,可以将点击事件监听器直接绑定到方法上,而不需要为每个按钮设置 OnClickListener。
java
@OnClick(R.id.button)
public void onButtonClick() {
// 点击事件处理逻辑
}
3、资源绑定:
ButterKnife 提供了多种不同类型的注解,例如 @BindString
用于绑定字符串资源,@BindColor
用于绑定颜色资源等等,这些注解可以简化对资源的访问和使用。
- **
@BindString
:**用于绑定字符串资源。
java
@BindString(R.string.app_name)
String appName;
2. @BindColor
:用于绑定颜色资源。
java
@BindColor(R.color.primary_color)
int primaryColor;
**3.****@BindDimen
:**用于绑定尺寸资源。
java
@BindDimen(R.dimen.text_size)
float textSize;
4.**@BindDrawable
:**用于绑定 drawable 资源。
java
@BindDrawable(R.drawable.ic_logo)
Drawable logoDrawable;
5.**@BindBitmap:**用于绑定 bitmap 资源。
java
@BindBitmap(R.drawable.img_bitmap)
Bitmap bitmap;
4.绑定多个视图元素:
使用 **@BindViews
**注解可以将多个视图元素绑定到一个 List 或数组中。
java
@BindViews({ R.id.text1, R.id.text2, R.id.text3 })
List<TextView> textViews;
5.绑定视图容器:
使用 @BindArray
注解可以将数组资源绑定到 Java 数组或 List 中,以方便访问和使用。
java
@BindArray(R.array.colors)
String[] colorsArray;
6.自定义绑定逻辑
java
public class CustomBinder implements ButterKnife.Binder {
@Override
public void bind(View view) {
// 自定义绑定逻辑
}
}
四、ButterKnife的例子
例1:在Activity中使用:
MainActivity :
java
package com.example.butterknifedemo01;
import androidx.appcompat.app.AppCompatActivity;
import butterknife.BindColor;
import butterknife.BindString;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnLongClick;
import butterknife.Unbinder;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@BindView(R.id.textView)
TextView mTextView;
@BindColor(R.color.teal_200)
int setTextColor;
@BindString(R.string.app_name)
String appName;
Unbinder mUnbinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定activity
mUnbinder = ButterKnife.bind(this);
}
@OnClick({R.id.textcolor, R.id.textsize, R.id.update_content})
public void onViewClicked(View view) {
int viewId = view.getId();
switch (viewId) {
case R.id.textcolor:
mTextView.setTextColor(setTextColor);
break;
case R.id.textsize:
mTextView.setTextSize(18);
break;
case R.id.update_content:
mTextView.setText(appName);
break;
}
}
@OnLongClick(R.id.long_on_click)
public void LongOnClick(){
Toast.makeText(this, "长按按钮", Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
// 解除绑定
mUnbinder.unbind();
}
}
activity_main:
html
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/long_on_click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="长按按钮事件"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<Button
android:id="@+id/update_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="换文本框内容"
app:layout_constraintBottom_toTopOf="@+id/long_on_click"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<Button
android:id="@+id/textsize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="字体大小"
app:layout_constraintBottom_toTopOf="@+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/textcolor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="字体颜色"
app:layout_constraintBottom_toTopOf="@+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textsize" />
</androidx.constraintlayout.widget.ConstraintLayout>
运行结果:
例2:在fragment在使用:
MyFragment :
java
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MyFragment extends Fragment {
@BindView(R.id.textView)
TextView mTextView;
@BindView(R.id.button)
Button mButton;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my, container, false);
ButterKnife.bind(this, view);
return view;
}
@OnClick(R.id.button)
public void onButtonClick() {
mTextView.setText("Button Clicked");
}
}
fragment_my:
html
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello ButterKnife" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Me" />
</LinearLayout>
与Activity对比:
在 Activity 中使用 ButterKnife,通常是在 onCreate()
方法中使用 ButterKnife.bind(this)
进行绑定操作。而在 Fragment 中,需要在 onCreateView()
方法中使用 ButterKnife.bind(this, view)
进行绑定操作,其中 view
是 Fragment 的根视图。
例3:在适配器中使用
MainActivity :
java
package com.example.butterknifedome02;
import android.os.Bundle;
import android.widget.LinearLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity {
@BindView(R.id.recyclerView)
RecyclerView mRecyclerView;
private MyAdapter mAdapter;
private List<String> mDataList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initData();
initView();
}
private void initData() {
// 初始化数据列表
mDataList = new ArrayList<>();
mDataList.add("Item 1");
mDataList.add("Item 2");
mDataList.add("Item 3");
// 添加更多数据...
}
private void initView() {
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
// 创建并设置适配器
mAdapter = new MyAdapter(this, mDataList);
mRecyclerView.setAdapter(mAdapter);
}
}
MyAdapter :
java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private Context mContext;
private List<String> mDataList;
public MyAdapter(Context context, List<String> dataList) {
mContext = context;
mDataList = dataList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_layout, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
String item = mDataList.get(position);
holder.bind(item);
}
@Override
public int getItemCount() {
return mDataList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.textView)
TextView mTextView;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bind(String item) {
mTextView.setText(item);
}
}
}
activity_main:
html
<LinearLayout 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:orientation="vertical"
android:paddingLeft="16dp"
android:paddingTop="16dp"
android:paddingRight="16dp"
android:paddingBottom="16dp"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
item_layout:
html
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
运行结果:
总结:在适配器中使用 ButterKnife 则是在 ViewHolder 的构造函数中进行绑定操作。
五、 ButterKnife使用的注意事项
**1、导入 ButterKnife 库:**确保在项目的 build.gradle 文件中添加了 ButterKnife 的依赖项,并进行了正确的同步操作。例如,在模块的 build.gradle 文件中添加以下依赖项:
java
dependencies {
implementation 'com.jakewharton:butterknife:10.2.3' // 添加此依赖
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3' // 添加此规则
}
2、绑定视图: 在需要进行视图绑定的类(如 Activity、Fragment 或 ViewHolder)中使用 ButterKnife.bind(this)
方法来进行视图绑定操作。确保在合适的生命周期方法中调用该方法,以避免空指针异常或绑定失败。例如,在 Activity 的 onCreate()
方法中绑定视图:
java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
// ...
}
3、注解使用: 在布局文件中的视图上使用 ButterKnife 的注解进行标记,以便 ButterKnife 能够识别并进行绑定。常用的注解包括 @BindView
、@OnClick
、@OnLongClick
等。确保注解的使用位置正确,并且注解的参数类型与视图的类型匹配。
4、解除绑定: 在不再需要使用 ButterKnife 进行视图绑定的时候,要确保及时解除绑定,以避免潜在的内存泄漏问题。通常,在相应的生命周期方法中调用 ButterKnife.unbind(this)
方法来解除绑定,例如在 Fragment 的 onDestroyView()
方法中解除绑定:
java
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
}