文章目录

ViewBinding使用方法1.build.gradle中开启2.代码中使用普通ActivityFragmentAdapterinclude

View Binding 的传统使用方式与findViewById的区别与DataBinding的对别

ViewBinding

ViewBinding是Google在2019年I/O大会上公布的一款Android视图绑定工具,在Android Studio 3.6中添加的一个新功能,更准确的说,它是DataBinding的一个更轻量变体

使用方法

1.build.gradle中开启

在build.gradle文件中的android节点添加如下代码:

android {

...

buildFeatures {

viewBinding true

}

}

重新编译后系统会为每个布局文件生成对应的Binding类,该类中包含对应布局中具有id的所有视图的直接引用。

如果项目中存在多个模块,则需要在每个模块的build.gradle文件中都加上该配置。 假设某个布局文件的名称为result_profile.xml:所生成的绑定类的名称就为ResultProfileBinding。 如果布局中的控件没有ID,那么绑定类中不存在对它的引用。

每个绑定类还包含一个 getRoot() 方法,用于为相应布局文件的根视图提供直接引用。

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

...

tools:viewBindingIgnore="true" >

...

2.代码中使用

普通Activity

class SplashActivity : BaseActivity() {

private lateinit var binding: ActivitySplashBinding

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

binding = ActivitySplashBinding.inflate(layoutInflater)

setContentView(binding.root)

// mtv为xml中定义的id

binding.mtv.text = "fuck the world"

}

}

Fragment

在Fragment中,我们需要进行额外的工作来避免内存泄漏,方法是在onDestroyView方法中将ViewBinding引用设置为null。 具体如下:

class HomeFragment : Fragment() {

private var _binding: HomeFragmentBinding? = null

// 只在onCreateView和onDestroyView之间有效

private val binding get() = _binding!!

override fun onCreateView(

inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {

_binding = ResultProfileBinding.inflate(inflater, container, false)

return binding.root

}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

super.onViewCreated(view, savedInstanceState)

binding.tvHelloWorld.text = "Hello Android!"

}

override fun onDestroyView() {

super.onDestroyView()

_binding = null

}

}

这里使用了两个不同的变量,并且在onDestroyView()中将_binding变量设置为null。 这是因为碎片的生命周期与活动的生命周期不同,并且碎片有着比它们的视图更长的生命周期,所以如果我们不将其设置为null,可能会发生内存泄漏。 另一个变量用于避免使用!!进行空检查!!通过使一个变量可以为null而另一个变量不为null。

Adapter

还有在Adapter中的使用,因为布局不是只创建一次,而是每个item都会创建,不能像上面那样在Adapter里写一个binding全局变量,不然binding只会得到最后一次创建的视图。所以binding对象应该是给ViewHolder持有。具体如下:

class TextAdapter(private val list: List) : RecyclerView.Adapter() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TextViewHolder {

val binding = ItemTextBinding.inflate(LayoutInflater.from(parent.context), parent, false)

//在生成时先给binding赋值,然后传参给ViewHolder的构造器

return TextViewHolder(binding)

}

override fun onBindViewHolder(holder: TextViewHolder, position: Int) {

val content = list[position]

holder.binding.tvContent.text = content

}

override fun getItemCount() = list.size

class TextViewHolder(val binding : ItemTextBinding) : RecyclerView.ViewHolder(binding.root)

}

include

ViewBinding同样可以被用于include中。 需要对include指定id,通过id来获取,例如:

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="wrap_content">

android:id="@+id/toolbar"

android:layout_width="0dp"

android:layout_height="?actionBarSize"

android:background="?colorPrimary"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toTopOf="parent" />

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/appbar"

layout="@layout/app_bar"

app:layout_constraintTop_toTopOf="parent" />

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

val binding: MainLayoutBinding = MainLayoutBinding.inflate(layoutInflater)

setContentView(binding.root)

setSupportActionBar(binding.appbar.toolbar)

//不多说

}

View Binding 的传统使用方式

创建和销毁viewBinding的样板代码如果有很多Fragment,每一个都要拷贝一份相同的代码viewBinding 属性是可空的,并且可变的,这可不太妙

而且使用起来不方便,我们希望用更简单的方式,例如:

class MainActivity : AppCompatActivity() {

private val binding by viewBinding(ActivityMainBinding::inflate)

}

怎么办呢?用强大Kotlin委托来重构它。通过属性委托可以自动执行inflate()方法和setContentView()方法。

与findViewById的区别

与使用 findViewById 相比,视图绑定具有一些很显著的优点:

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

这些差异意味着布局和代码之间的不兼容将会导致构建在编译时(而非运行时)失败。

与DataBinding的对别

ViewBinding与DataBinding均会生成可用于直接引用视图的绑定类。但是,ViewBinding旨在处理更简单的用例,与DataBinding相比,具有以下优势:

更快的编译速度 视图绑定不需要处理注释,因此编译时间更短。易于使用 视图绑定不需要特别标记的XML布局文件,因此在应用中采用速度更快。在模块中启用视图绑定后,它会自动应用于该模块的所有布局。

反过来,与数据绑定相比,视图绑定也具有以下限制:

视图绑定不支持布局变量或布局表达式,因此不能用于直接在XML布局文件中声明动态界面内容。视图绑定不支持双向数据绑定。

考虑到这些因素,在某些情况下,最好在项目中同时使用视图绑定和数据绑定。您可以在需要高级功能的布局中使用数据绑定,而在不需要高级功能的布局中使用视图绑定。

参考文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: