Android View Binding的使用
转载请标明出处: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的使用相关推荐
- Android View Binding使用介绍
前言 Android Studio稳定版发布了3.6版本,带来了一些新变化:首先外观,启动页变了,logo改了,更显现代化:增加Multi Preview功能,能同时预览多个尺寸屏幕的显示效果:模拟器 ...
- Android Data Binding 详细介绍与使用
构建环境 首先,确保能使用Data Binding,需要下载最新的 Support repository.否则可能报错,如图: 在模块的build.gradle文件中添加dataBinding配置 a ...
- 你好, View Binding! 再次再见, findViewById!
作为一个 Android 开发者, 你一定听说过 findViewById. 这个方法可以根据 ID 去匹配对应的 View. 实现了类似功能或者增强了其功能的还有: Butter Knife(Kot ...
- Android Data Binding 入门
Android Data Binding 入门 参考 http://www.cnblogs.com/lizebo/p/5474366.html 配置环境 build.gradle android {. ...
- Android Data Binding Library 官方文档(译)
地址:https://developer.android.google.cn/topic/libraries/data-binding/index.html 本文地址:http://blog.csdn ...
- 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 这个问题自己大致在 ...
- 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 ...
- Android编程:解决异常“android.view.InflateException: Binary XML file line # : Error inflating class”
我一般都是在1和4 遇到,记录一下. 今天写程序发现一个问题,就是XML中报出Android.view.InflateException异常,可能的原因有: 1.XML中使用到得组件名称是否书写正确( ...
- Android View框架的measure机制
Android中View框架的工作机制中,主要有三个过程: 1.View树的测量(measure)Android View框架的measure机制 http://www.cnblogs.com/xyh ...
最新文章
- php操作MySQL
- 计算机系统的可靠性可以用什么来表示,系统分析师考试计算机系统的可靠性指标...
- 听小鹏讲废话之OSI
- 中年高校教师、行政人员的21个特征!
- VMweare 安装 Kali Linux 系统
- (Electronic WorkBench)EWB仿真JK触发器
- 数据结构by王卓老师
- 考研复习(8)-图的基本操作
- 干货 | 机器学习在web攻击检测中的应用实践
- avalon2学习教程14动画使用
- 关于Android 微信APP支付开发中遇到的问题
- 深入Guerrilla Games解密次世代开山大作《杀戮地带暗影坠落》(The technology of Killzone Shadow Fall)
- 计算机 科研进度安排,研究计划进度安排及预期目标-浙江大学现代教务管理系统.doc...
- python实现LU分解
- linspace函数
- vscode配置html页面自动刷新,Vscode关闭自动更新设置
- IP-guard23个功能模块简介
- Qt滚动区域QScrollArea
- 《哪来的天才-练习中的平凡与伟大》阅读笔记与心得
- valgrind内存泄露和线程竞态检测
热门文章
- 镜像电流源特点_9000大型地网变频大电流接地特性测量系统介绍
- Android 使用ContentProvider(内容提供者)查询手机联系
- OpenCV人脸检测与人脸识别
- plus 什么是mybais_【mybatis-plus】什么是乐观锁?如何实现“乐观锁”
- 悉尼大学 伦敦大学联合出品:知识蒸馏最新综述
- ACL 2021 | 为什么机器阅读理解模型会学习走捷径?
- 算法分析与设计-实验三 贪心算法设计
- HDU2091 空心三角形 水题
- git/码云上关于项目的一些操作:初始化、克隆、上传修改等
- 【Windows部署】Telegraf + Influxdb + Grafana 安装及使用配置(含百度云盘资源 + demo脚本)