Android: View binding - ButterKnife

Table of contents

1. Introduction to ButterKnife

2. Advantages of ButterKnife:

3. Use of ButterKnife

Build.gradle adds ButterKnife dependency:

1. View binding:

2. Click event binding:

 3. Resource binding:

 4. Bind multiple view elements:

 5. Bind the view container:

6. Custom binding logic 

4. Example of ButterKnife

Example 1: Use in Activity:

MainActivity : 

activity_main:

operation result: 

Example 2: Use in fragment:

MyFragment :

 fragment_my:

Compare with Activity: 

 Example 3: Use in adapter

 MainActivity :

 MyAdapter :

 activity_main:

item_layout: 

operation result:

 5. Precautions when using ButterKnife

1. Introduction to ButterKnife

        ButterKnife is an Android view binding framework developed by Jake Wharton. It simplifies view binding operations in Android by using annotations, reducing the workload of manually writing tedious findViewById() code.

2. Advantages of ButterKnife:

1. Reduce redundant code: Using ButterKnife can significantly reduce redundant code in Android projects. Traditionally, you need to manually write a lot of findViewById() code to find and bind view elements, but ButterKnife uses annotations for view binding, making the code more concise and readable.

2. Improve development efficiency : By automating the view binding process, ButterKnife can save developers time and energy during the development process. It simplifies the operation of view binding and reduces the workload of manually writing template code, thereby speeding up development.

3. Reduce the risk of errors: Since ButterKnife automatically handles view binding, it reduces the process of manually writing findViewById(), thus reducing the possibility of errors. By using ButterKnife, you can avoid null pointer exceptions or other errors caused by cumbersome view binding.

4. Supports multiple binding types: In addition to conventional view binding, ButterKnife also provides various annotations that can easily bind strings, colors, arrays and other resources, further simplifying access and use of resources.

5. Easy to extend and customize: ButterKnife has a flexible architecture, and its functions can be extended and customized through custom annotations and custom binding logic. Developers can customize annotation processors or implement ButterKnife's Binder interface according to project needs to meet specific binding requirements.

        In general, ButterKnife provides a concise, efficient and easy-to-use way to bind Android views, reducing the complexity of development and improving development efficiency and code quality. It has become one of the favorite tools of the majority of Android developers.

3. Use of ButterKnife

Build.gradle adds ButterKnife dependency:

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

1. View binding:

ButterKnife can automatically bind the view elements in the layout file by using the @BindView         annotation in the code , without manually calling the findViewById() method. Use  @BindView annotations to bind view elements directly to variables in your code.

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

2. Click event binding:

        By using  the @OnLongClick() annotation, you can bind the click event listener directly to the method without the need to set an OnClickListener for each button.@OnClick 

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

 3. Resource binding:

        ButterKnife provides many different types of annotations, such as @BindStringfor binding string resources, @BindColorfor binding color resources, etc. These annotations can simplify access and use of resources.

  1. @BindString: Used to bind string resources.
@BindString(R.string.app_name)
String appName;

    2.:@BindColor Used to bind color resources.

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

 3.@BindDimen: Used to bind size resources.

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

  4 @BindDrawable.: Used to bind drawable resources.

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

 5.@BindBitmap: Used to bind bitmap resources.

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

 4. Bind multiple view elements:

        Use @BindViews annotations to bind multiple view elements to a List or array.

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

 5. Bind the view container:

@BindArray Array resources can be bound to Java arrays or Lists using annotations for easy access and use         . 

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

6. Custom binding logic 

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

4. Example of ButterKnife

Example 1: Use in 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>

operation result: 

Example 2: Use in 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>

Compare with Activity: 

       When using ButterKnife in Activity, it is usually  onCreate() used in methods  ButterKnife.bind(this) for binding operations. In Fragment, you need to  onCreateView() use it in the method  ButterKnife.bind(this, view) for binding operation, which  view is the root view of Fragment. 

 Example 3: Use in adapter

 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>

operation result:

Summary: When using ButterKnife in an adapter, the binding operation is performed in the constructor of ViewHolder.  

 5. Precautions when using ButterKnife

1. Import the ButterKnife library: Make sure to add ButterKnife dependencies in the project's build.gradle file and perform correct synchronization operations. For example, add the following dependency in your module's build.gradle file:

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

2. Bind the view: Use the method in the class that requires view binding (such as Activity, Fragment or ViewHolder) ButterKnife.bind(this)to perform the view binding operation. Make sure to call this method in an appropriate lifecycle method to avoid null pointer exceptions or binding failures. onCreate()For example, bind the view in the  Activity method:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);
    // ...
}

 3. Use of annotations: Use ButterKnife's annotations to mark the views in the layout file so that ButterKnife can recognize and bind them. Commonly used annotations include @BindView, @OnClick, @OnLongClicketc. Make sure that the annotation is used in the correct location and that the annotation parameter type matches the type of the view.

 4. Unbinding: When you no longer need to use ButterKnife for view binding, be sure to unbind it in time to avoid potential memory leaks. Usually, call the method in the corresponding life cycle method ButterKnife.unbind(this)to unbind, for example, onDestroyView()unbind in the Fragment method:

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

Guess you like

Origin blog.csdn.net/A125679880/article/details/131969235