安卓:视图绑定——ButterKnife

目录

一、ButterKnife介绍

二、ButterKnife优点:

三、ButterKnife的使用

build.gradle添加 ButterKnife 依赖:

1、视图绑定:

2、点击事件绑定:

 3、资源绑定:

 4.绑定多个视图元素:

 5.绑定视图容器:

6.自定义绑定逻辑 

四、ButterKnife的例子

例1:在Activity中使用:

MainActivity : 

activity_main:

运行结果: 

例2:在fragment在使用:

MyFragment :

 fragment_my:

与Activity对比: 

 例3:在适配器中使用

 MainActivity :

 MyAdapter :

 activity_main:

item_layout: 

运行结果:

 五、 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 依赖:

dependencies {
    implementation 'com.jakewharton:butterknife:10.2.3' // 添加此依赖
    annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3' // 添加此规则
}

1、视图绑定:

        ButterKnife 可以通过在代码中使用注解@BindView来自动绑定布局文件中的视图元素,无需手动调用 findViewById() 方法。使用 @BindView 注解可以将视图元素直接与代码中的变量进行绑定。

@BindView(R.id.textView)
TextView textView;

2、点击事件绑定:

        通过使用 @OnClick @OnLongClick( )注解,可以将点击事件监听器直接绑定到方法上,而不需要为每个按钮设置 OnClickListener。

@OnClick(R.id.button)
public void onButtonClick() {
    // 点击事件处理逻辑
}

 3、资源绑定:

        ButterKnife 提供了多种不同类型的注解,例如 @BindString 用于绑定字符串资源,@BindColor 用于绑定颜色资源等等,这些注解可以简化对资源的访问和使用。

  1. @BindString用于绑定字符串资源。
@BindString(R.string.app_name)
String appName;

    2.@BindColor:用于绑定颜色资源。

@BindColor(R.color.primary_color)
int primaryColor;

 3.@BindDimen用于绑定尺寸资源。

@BindDimen(R.dimen.text_size)
float textSize;

  4.@BindDrawable用于绑定 drawable 资源。

@BindDrawable(R.drawable.ic_logo)
Drawable logoDrawable;

 5.@BindBitmap用于绑定 bitmap 资源。

@BindBitmap(R.drawable.img_bitmap)
Bitmap bitmap;

 4.绑定多个视图元素:

        使用 @BindViews 注解可以将多个视图元素绑定到一个 List 或数组中。

@BindViews({ R.id.text1, R.id.text2, R.id.text3 })
List<TextView> textViews;

 5.绑定视图容器:

        使用 @BindArray 注解可以将数组资源绑定到 Java 数组或 List 中,以方便访问和使用。

@BindArray(R.array.colors)
String[] colorsArray;

6.自定义绑定逻辑 

public class CustomBinder implements ButterKnife.Binder {
    @Override
    public void bind(View view) {
        // 自定义绑定逻辑
    }
}

四、ButterKnife的例子

例1:在Activity中使用:

MainActivity : 

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:

<?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 :

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:

<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 :

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 :

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:

<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: 

<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 文件中添加以下依赖项:

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() 方法中绑定视图: 

@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() 方法中解除绑定:

@Override
public void onDestroyView() {
    super.onDestroyView();
    ButterKnife.unbind(this);
}

猜你喜欢

转载自blog.csdn.net/A125679880/article/details/131969235