转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/120751996
本文出自【赵彦军的博客】

文章目录

  • 什么是View Binding
  • 如何启用View Binding 功能
  • 怎么去使用View Binding
    • Activity 绑定视图
    • Fragment 绑定视图
  • 使用View Binding 写的基类
    • 1、通过反射的方式(这种方式不推荐使用,会有混淆问题)
    • 2、不通过反射的方式
  • RecyclerView ViewHolder 使用

什么是View Binding

View Binding是Android Studio 3.6推出的新特性,目的是为了替代findViewById(内部实现还是使用findViewById)。。在启动视图绑定后,系统会为改模块中的每个xml文件生成一个绑定类,绑定类的实例包含对在相应布局中具有 ID 的所有视图的直接引用。

View Binding 的优点

  • Null 安全:由于视图绑定会创建对视图的直接引用,因此不存在因视图 ID 无效而引发 Null 指针异常的风险。此外,如果视图仅出现在布局的某些配置中,则绑定类中包含其引用的字段会使用 @Nullable 标记。
  • 类型安全:每个绑定类中的字段均具有与它们在 XML 文件中引用的视图相匹配的类型。这意味着不存在发生类转换异常的风险。

如何启用View Binding 功能

android {buildFeatures {viewBinding true}
}

如果想在生成绑定类时忽略某个布局文件,将 tools:viewBindingIgnore="true" 属性添加到相应布局文件的根视图中:

<?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:viewBindingIgnore="true"tools:context=".MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

怎么去使用View Binding

为用视图绑定功能后,系统会为该模块中包含的每个 XML 布局文件生成一个绑定类。这个类的类名是以xml布局文件名去掉下换线后,单词首字母大写加上Binding命名的。如 activity_main.xml生成的类 ActivityMainBinding.

Activity 绑定视图

  • 第一步:调用生成的绑定类中包含的静态 inflate() 方法。此操作会创建该绑定类的实例以供 Activity 使用。

  • 第二步:通过调用 getRoot() 方法或使用 Kotlin 属性语法获取对根视图的引用。

  • 第三步:将根视图传递到 setContentView(),使其成为屏幕上的活动视图。

<?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"><TextViewandroid:id="@+id/tv"android:layout_width="100dp"android:layout_height="100dp"android:background="#77f"android:text="赵彦军"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

使用:

class MainActivity : AppCompatActivity() {lateinit var binding: ActivityMainBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)//关键代码binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)//获取控件binding.tv.setOnClickListener {Toast.makeText(this, "hahha", Toast.LENGTH_SHORT).show()}}
}

Fragment 绑定视图

如何在 Fragment 中使用视图绑定 请在 Fragment 的 onCreateView()方法中执行以下步骤(注意:Fragment 的存在时间比其视图长。请务必在 Fragment 的 onDestroyView() 方法中清除对绑定类实例的所有引用。)

  • 调用生成的绑定类中包含的静态 inflate() 方法。此操作会创建该绑定类的实例以供 Fragment 使用。

  • 通过调用 getRoot() 方法或使用 Kotlin 属性语法获取对根视图的引用。

  • 从 onCreateView() 方法返回根视图,使其成为屏幕上的活动视图

//fragment_my.xml
<?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"><Buttonandroid:id="@+id/button"android:layout_width="wrap_content"android:layout_height="40dp"android:text="这是Fragment按钮"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toBottomOf="@+id/textView" /><TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="40dp"android:gravity="center"android:text="这是FragmentTextView"app:layout_constraintBottom_toTopOf="@+id/button"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>
public class MyFragment extends Fragment {private FragmentMyBinding binding;public MyFragment() {}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {binding = FragmentMyBinding.inflate(inflater, container, false);return binding.getRoot();}@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);binding.textView.setText("这是Fragment");binding.button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Log.d("Fragment", "点击了按钮");}});}@Overridepublic void onDestroy() {super.onDestroy();binding = null;}

在onViewCreated中使用View Binding

//在onViewCreated中使用View Binding
public class MyFragment extends Fragment {private FragmentMyBinding binding;public MyFragment() {}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {return inflater.inflate(R.layout.fragment_my,container,false);}@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);FragmentMyBinding binding = FragmentMyBinding.bind(view);this.binding = binding;binding.textView.setText("这是Fragment");binding.button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Log.d("Fragment", "点击了按钮");}});}@Overridepublic void onDestroy() {super.onDestroy();binding = null;}

使用View Binding 写的基类

1、通过反射的方式(这种方式不推荐使用,会有混淆问题)

Activity 基类设计

//Java
public class BaseActivity<T extends ViewBinding> extends AppCompatActivity {protected T viewBinding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();Class cls = (Class) type.getActualTypeArguments()[0];try {Method inflate = cls.getDeclaredMethod("inflate", LayoutInflater.class);viewBinding = (T) inflate.invoke(null, getLayoutInflater());setContentView(viewBinding.getRoot());} catch (NoSuchMethodException | IllegalAccessException| InvocationTargetException e) {e.printStackTrace();}}
}//使用public class MainActivity extends BaseActivity<ActivityMainBinding> {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);viewBinding.button.setText("这是 MainActivity ViewBinding");viewBinding.button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Log.d("MainView","点击按钮");}});}
}
//Kotlin
open class BaseActivity<T : ViewBinding> : AppCompatActivity() {protected lateinit var binding: Toverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val type = javaClass.genericSuperclass as ParameterizedTypeval aClass = type.actualTypeArguments[0] as Class<*>val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java)binding = method.invoke(null, layoutInflater) as TsetContentView(binding.root)}
}class MainActivity : BaseActivity<ActivityMainBinding>() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding.textView.text = "这是MainActivity"}
}

Fragment 基类设计

//Java
public class BaseFragment<T extends ViewBinding> extends Fragment {protected T viewBinding;@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();Class cls = (Class) type.getActualTypeArguments()[0];try {Method inflate = cls.getDeclaredMethod("inflate", LayoutInflater.class, ViewGroup.class, boolean.class);viewBinding = (T) inflate.invoke(null, inflater, container, false);}  catch (NoSuchMethodException | IllegalAccessException| InvocationTargetException e) {e.printStackTrace();}return viewBinding.getRoot();}
}//使用
public class MainFragment extends BaseFragment<FragmentMainBinding>{@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);viewBinding.button.setText("这是 MainFragment ViewBinding");viewBinding.button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Log.d("MainView","点击按钮");}});}
}
//Kotlin
open class BaseFragment<T:ViewBinding>:Fragment(){lateinit var binding: Toverride fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {val type = javaClass.genericSuperclass as ParameterizedTypeval aClass = type.actualTypeArguments[0] as Class<*>val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java,ViewGroup::class.java,Boolean::class.java)binding = method.invoke(null,layoutInflater,container,false) as Treturn binding.root}
}class FirstFragment : BaseFragment<FragmentFirstBinding>() {override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)binding.textView.text = "这是FirstFragment"}
}

2、不通过反射的方式

Activity 基类设计

abstract class BaseActivity<T : ViewBinding> : AppCompatActivity() {private lateinit var _binding: Tprotected val binding get() = _binding;override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)_binding = getViewBinding()setContentView(_binding.root)}protected abstract fun getViewBinding(): T
}class MainActivity : BaseActivity<ActivityMainBinding>() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding.textView.text = "这是MainActivity"}override fun getViewBinding() = ActivityMainBinding.inflate(layoutInflater)
}

Fragment 基类设计

abstract class BaseFragment<T : ViewBinding> : Fragment() {private lateinit var _binding: Tprotected val binding get() = _binding;override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {_binding = getViewBinding(inflater, container)return _binding.root}protected abstract fun getViewBinding(inflater: LayoutInflater, container: ViewGroup?): T
}class FirstFragment : BaseFragment<FragmentFirstBinding>() {override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)binding.textView.text = "这是FirstFragment"}override fun getViewBinding(inflater: LayoutInflater,container: ViewGroup?) = FragmentFirstBinding.inflate(inflater, container, false)
}

RecyclerView ViewHolder 使用

方式一:

lass MyItemRecyclerViewAdapter(private val values: List<PlaceholderItem>
) : RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {return ViewHolder(FragmentItemBinding.inflate(LayoutInflater.from(parent.context),parent,false))}override fun onBindViewHolder(holder: ViewHolder, position: Int) {val item = values[position]holder.idView.text = item.idholder.contentView.text = item.content}override fun getItemCount(): Int = values.sizeclass ViewHolder(binding: FragmentItemBinding) : RecyclerView.ViewHolder(binding.root) {val idView: TextView = binding.itemNumberval contentView: TextView = binding.content}}

方式二:

class MyItemRecyclerViewAdapter(private val values: List<PlaceholderItem>
) : RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {return ViewHolder(FragmentItemBinding.inflate(LayoutInflater.from(parent.context),parent,false))}override fun onBindViewHolder(holder: ViewHolder, position: Int) {val item = values[position]holder.binding.itemNumber.text = item.id}override fun getItemCount(): Int = values.sizeclass ViewHolder(val binding: FragmentItemBinding) : RecyclerView.ViewHolder(binding.root)}

Android View Binding的使用相关推荐

  1. Android View Binding使用介绍

    前言 Android Studio稳定版发布了3.6版本,带来了一些新变化:首先外观,启动页变了,logo改了,更显现代化:增加Multi Preview功能,能同时预览多个尺寸屏幕的显示效果:模拟器 ...

  2. Android Data Binding 详细介绍与使用

    构建环境 首先,确保能使用Data Binding,需要下载最新的 Support repository.否则可能报错,如图: 在模块的build.gradle文件中添加dataBinding配置 a ...

  3. 你好, View Binding! 再次再见, findViewById!

    作为一个 Android 开发者, 你一定听说过 findViewById. 这个方法可以根据 ID 去匹配对应的 View. 实现了类似功能或者增强了其功能的还有: Butter Knife(Kot ...

  4. Android Data Binding 入门

    Android Data Binding 入门 参考 http://www.cnblogs.com/lizebo/p/5474366.html 配置环境 build.gradle android {. ...

  5. Android Data Binding Library 官方文档(译)

    地址:https://developer.android.google.cn/topic/libraries/data-binding/index.html 本文地址:http://blog.csdn ...

  6. Android运行时候报错:android.view.InflateException: Binary XML file line #19: Binary XML file lin

    Android运行时候报错:android.view.InflateException: Binary XML file line #19: Binary XML file lin 这个问题自己大致在 ...

  7. android.view.InflateException: Binary XML file line #7: Binary XML file line #7

    错误如下 11-21 08:19:44.040 3608-3608/com.leon.oldrecyclerview E/AndroidRuntime: FATAL EXCEPTION: main   ...

  8. Android编程:解决异常“android.view.InflateException: Binary XML file line # : Error inflating class”

    我一般都是在1和4 遇到,记录一下. 今天写程序发现一个问题,就是XML中报出Android.view.InflateException异常,可能的原因有: 1.XML中使用到得组件名称是否书写正确( ...

  9. Android View框架的measure机制

    Android中View框架的工作机制中,主要有三个过程: 1.View树的测量(measure)Android View框架的measure机制 http://www.cnblogs.com/xyh ...

最新文章

  1. php操作MySQL
  2. 计算机系统的可靠性可以用什么来表示,系统分析师考试计算机系统的可靠性指标...
  3. 听小鹏讲废话之OSI
  4. 中年高校教师、行政人员的21个特征!
  5. VMweare 安装 Kali Linux 系统
  6. (Electronic WorkBench)EWB仿真JK触发器
  7. 数据结构by王卓老师
  8. 考研复习(8)-图的基本操作
  9. 干货 | 机器学习在web攻击检测中的应用实践
  10. avalon2学习教程14动画使用
  11. 关于Android 微信APP支付开发中遇到的问题
  12. 深入Guerrilla Games解密次世代开山大作《杀戮地带暗影坠落》(The technology of Killzone Shadow Fall)
  13. 计算机 科研进度安排,研究计划进度安排及预期目标-浙江大学现代教务管理系统.doc...
  14. python实现LU分解
  15. linspace函数
  16. vscode配置html页面自动刷新,Vscode关闭自动更新设置
  17. IP-guard23个功能模块简介
  18. Qt滚动区域QScrollArea
  19. 《哪来的天才-练习中的平凡与伟大》阅读笔记与心得
  20. valgrind内存泄露和线程竞态检测

热门文章

  1. 镜像电流源特点_9000大型地网变频大电流接地特性测量系统介绍
  2. Android 使用ContentProvider(内容提供者)查询手机联系
  3. OpenCV人脸检测与人脸识别
  4. plus 什么是mybais_【mybatis-plus】什么是乐观锁?如何实现“乐观锁”
  5. 悉尼大学 伦敦大学联合出品:知识蒸馏最新综述
  6. ACL 2021 | 为什么机器阅读理解模型会学习走捷径?
  7. 算法分析与设计-实验三 贪心算法设计
  8. HDU2091 空心三角形 水题
  9. git/码云上关于项目的一些操作:初始化、克隆、上传修改等
  10. 【Windows部署】Telegraf + Influxdb + Grafana 安装及使用配置(含百度云盘资源 + demo脚本)