安卓:视图绑定——ButterKnife

news2024/10/7 10:18:47

目录

一、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);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/800291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

内核链表在用户程序中的移植和使用

基础知识 struct list_head {struct list_head *next, *prev; }; 初始化&#xff1a; #define LIST_HEAD_INIT(name) { (name)->next (name); (name)->prev (name);} 相比于下面这样初始化&#xff0c;前面初始化的好处是&#xff0c;处理链表的时候&#xff0c;不…

Python中运行取消Python console模式

在Python里run的时候突然会发现&#xff0c;进入的不是run模式&#xff0c;而是console模式&#xff0c;这种运行模式能保留你每次的运行历史&#xff0c;因为会重开一个运行小页面&#xff0c;关闭操作如下&#xff1a;

GAMES104里渲染等一些剩下的问题

渲染的一些剩下的问题 1. 如何理解渲染中的AO(环境光遮蔽) 环境光遮蔽 我们先从一个简单的效果开始—环境光遮蔽(Ambient Occlusion,以下简称AO)。大家可以看到&#xff0c;下图中的场景没有任何渲染效果&#xff0c;也没有任何着色效果&#xff0c;但场景呈现出了非常清晰的…

大数据学习教程:Linux 基础教程(上)

1 操作系统概述 1.1 计算机原理 现代计算机大部分都是基于冯.诺依曼结构&#xff0c;该结构的核心思想是将程序和数据都存放在计算机中&#xff0c;按存储器的存储程序首地址执行程序的第一条指令&#xff0c;然后进行数据的处理计算。 计算机应包括运算器、控制器、储存器、…

PLC学习的步骤与重点:

熟悉基础元器件的原理和使用方法&#xff1a;了解按钮、断路器、继电器、接触器、24V开关电源等基础元器件的原理和使用方法&#xff0c;并能够应用它们来实现简单的逻辑电路&#xff0c;例如电机的正反转和单按钮的启停控制。 掌握PLC的接线方法&#xff1a;了解PLC的输入输出…

【C++进阶:map和set】

本节涉及到的所有代码见以下链接&#xff0c;欢迎参考指正&#xff01; ​​​​​​​ practice: 课程代码练习 - Gitee.comhttps://gitee.com/ace-zhe/practice/tree/master/map%E5%92%8Cset ​​​​​​​ 关联式容器 在C初阶阶段&#xff0c;已经学习并总了STL中的部分…

麒麟信安携手先进数通发布“多云协同,加速推进服务器虚拟化国产平滑迁移”信创联合解决方案

金融行业是现代经济的核心&#xff0c;金融行业信息技术应用创新是关系“国家安全”和“科技强国”战略的重要工程。为满足银行等金融机构数字化转型和信创发展的双重需求&#xff0c;麒麟信安与北京先进数通信息技术股份公司携手推出“多云协同&#xff0c;加速推进服务器虚拟…

Elisp之message为内容增加颜色(二十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

驱动 CAN总线

Controller Area Network&#xff08;控制器局部网络&#xff09;是一种有效支持分布式控制或实时控制的串行异步半双工的现场总线&#xff0c;支持多主机多从机&#xff0c;需要 CAN控制器 和 CAN收发器 的硬件支持 标准内容ISO 11898-1:2015定义数据链路层&#xff08;包括逻…

「二叉树与递归的一些框架思维」

文章目录 0 二叉树1 思路2 刷题2.1 二叉树的最大深度题解Code结果 2.2 二叉树的直径题解Code结果 2.3 在每个树行中找最大值题解Code结果 2.4 翻转二叉树题解Code结果 2.5 二叉树展开为链表题解Code结果 2.6 每日一题&#xff1a;数组中两元素的最大乘积题解Code结果 0 二叉树 …

华为开源自研AI框架昇思MindSpore应用案例:Vision Transformer图像分类

目录 一、环境准备1.进入ModelArts官网2.使用CodeLab体验Notebook实例 二、环境准备与数据读取三、模型解析Transformer基本原理Attention模块 Transformer EncoderViT模型的输入整体构建ViT 四、模型训练与推理模型训练模型验证模型推理 近些年&#xff0c;随着基于自注意&…

Spring——Spring是什么?IoC容器是什么?

文章目录 前言一、Spring是什么1.IoC 容器 —— 容器2.IoC 容器 —— IoC传统程序开发控制反转式程序开发 3.Spring IoC 二、DI是什么总结 前言 本人是一个普通程序猿!分享一点自己的见解,如果有错误的地方欢迎各位大佬莅临指导,如果你也对编程感兴趣的话&#xff0c;互关一下…

Vue2基础四、生命周期

零、文章目录 Vue2基础四、生命周期 1、生命周期 Vue生命周期&#xff1a;一个Vue实例从 创建 到 销毁 的整个过程。生命周期四个阶段&#xff1a;① 创建 ② 挂载 ③ 更新 ④ 销毁 创建阶段&#xff1a;创建响应式数据挂载阶段&#xff1a;渲染模板更新阶段&#xff1a;修改…

基于K8s环境·使用ArgoCD部署Jenkins和静态Agent节点

今天是「DevOps云学堂」与你共同进步的第 47天 第⑦期DevOps实战训练营 7月15日已开营 实践环境升级基于K8s和ArgoCD 本文节选自第⑦期DevOps训练营 &#xff0c; 对于训练营的同学实践此文档依赖于基础环境配置文档&#xff0c; 运行K8s集群并配置NFS存储。实际上只要有个K8s集…

Spring Security内置过滤器详解

相关文章&#xff1a; OAuth2的定义和运行流程Spring Security OAuth实现Gitee快捷登录Spring Security OAuth实现GitHub快捷登录Spring Security的过滤器链机制Spring Security OAuth Client配置加载源码分析 文章目录 前言OAuth2AuthorizationRequestRedirectFilterOAuth2Log…

matlab多线程,parfor循环进度,matlab互斥锁

一. 内容简介 matlab多线程&#xff0c;parfor循环进度&#xff0c;matlab互斥锁 二. 软件环境 2.1 matlab 2022b 2.2代码链接 https://gitee.com/JJW_1601897441/csdn 三.主要流程 3.1 matlab多线程 有好几种&#xff0c;最简单的&#xff0c;最好理解的就是parfor&am…

cpolar内网穿透外网远程访问本地网站

文章目录 cpolar内网穿透外网远程访问本地网站 cpolar内网穿透外网远程访问本地网站 在现代人的生活中&#xff0c;电脑是离不开的重要设备&#xff0c;大家看到用到的各种物品都离不开电脑的支持。尽管移动电子设备发展十分迅速&#xff0c;由于其自身存在的短板&#xff0c;…

Leetcode-每日一题【剑指 Offer 66. 构建乘积数组】

题目 给定一个数组 A[0,1,…,n-1]&#xff0c;请构建一个数组 B[0,1,…,n-1]&#xff0c;其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即 B[i]A[0]A[1]…A[i-1]A[i1]…A[n-1]。不能使用除法。 示例: 输入: [1,2,3,4,5]输出: [120,60,40,30,24] 提示&#xff1a; 所…

SSIS对SQL Server向Mysql数据转发表数据 (三)

1、在控制流界面&#xff0c;在左侧的组件里&#xff0c;添加一个“序列容器组件”和一个“数据流任务组件” 2、双击数据流任务&#xff0c;进入到数据流界面&#xff0c;然后再在左面添加一个OLE DB 源组件、目标源组件 3、右键源组件&#xff0c;编辑&#xff0c;选择好相关…

虎年现货黄金投资布局图

参与现货黄金交易的主要目的&#xff0c;是为了根据行情走势的变动&#xff0c;把握一些较佳的获利机会&#xff0c;在这样的一个过程中&#xff0c;如果投资者能够提前把布局的图表画好&#xff0c;那么就可能获得事半功倍的效果&#xff0c;而本文将为大家简单的介绍&#xf…