ViewBinding是Android开发中引入的一种新的视图绑定机制。在传统的Android开发中,我们通过调用findViewById()
方法来获取布局文件中的视图对象,然后进行操作。这种方式存在一些问题,比如需要手动查找和引用视图,容易出现空指针异常,而且代码冗长。
ViewBinding通过使用自动生成的绑定类,使视图绑定更加简单和类型安全。它利用了注解处理器,在编译时生成一个与布局文件相关联的绑定类。这个绑定类包含了布局文件中的所有视图对象,并提供了相应的getter方法,可以直接访问这些视图。
使用ViewBinding的好处包括:
findViewById()
方法,可以直接通过生成的绑定类来获取视图对象。在build.gradle(:app)
- android {
- ...
- viewBinding {
- enabled true
- }
- }
- class MainActivity : AppCompatActivity() {
- lateinit var binding: ActivityMainBinding
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- binding=ActivityMainBinding.inflate(layoutInflater)
- setContentView(R.layout.activity_main)
- }
- }
- class MainFragment : Fragment() {
-
- private var _binding: FragmentMainBinding? = null
-
- private val binding get() = _binding!!
-
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
- _binding = FragmentMainBinding.inflate(inflater, container, false)
- return binding.root
- }
-
- override fun onDestroyView() {
- super.onDestroyView()
- _binding = null
- }
-
- }
- class FruitAdapter(val fruitList: List
) : RecyclerView.Adapter() { -
- inner class ViewHolder(binding: FruitItemBinding) : RecyclerView.ViewHolder(binding.root) {
- val fruitImage: ImageView = binding.fruitImage
- val fruitName: TextView = binding.fruitName
- }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- val binding = FruitItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
- return ViewHolder(binding)
- }
-
- override fun onBindViewHolder(holder: ViewHolder, position: Int) {
- val fruit = fruitList[position]
- holder.fruitImage.setImageResource(fruit.imageId)
- holder.fruitName.text = fruit.name
- }
-
- override fun getItemCount() = fruitList.size
- }
include标签的布局
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <Button
- android:id="@+id/back"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:text="Back" />
-
- <TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:text="Title"
- android:textSize="20sp" />
-
- <Button
- android:id="@+id/done"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:text="Done" />
-
- RelativeLayout>
activity_main.xml中引入include标签的布局,一定要记得给include的布局加上id属性,不然到MainActivity中就找不到
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <include
- android:id="@+id/titleBar"
- layout="@layout/titlebar" />
- ...
- LinearLayout>
MainActivity中通过include布局的id来使用viewBinding
- class MainActivity : AppCompatActivity() {
-
- private lateinit var binding: ActivityMainBinding
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- binding = ActivityMainBinding.inflate(layoutInflater)
- setContentView(binding.root)
- binding.titleBar.title.text = "Title"
- binding.titleBar.back.setOnClickListener {
- }
- binding.titleBar.done.setOnClickListener {
- }
- }
-
- }
merge标签的布局
- <merge xmlns:android="http://schemas.android.com/apk/res/android">
-
- <Button
- android:id="@+id/back"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:text="Back" />
-
- <TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:text="Title"
- android:textSize="20sp" />
-
- <Button
- android:id="@+id/done"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:text="Done" />
-
- merge>
activity_main.xml中引入merge标签的布局,与include不同的是,在引入时去掉id属性防止崩溃:
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <include
- layout="@layout/titlebar" />
-
- LinearLayout>
MainActivity中通过创建两个viewBinding,一个是activity_main.xml的,另一个是我们引入的merge标签的,然后使用merge标签自动生成的viewBinding的bind方法绑定到activity_main.xml的viewBinding中。
- class MainActivity : AppCompatActivity() {
-
- private lateinit var binding: ActivityMainBinding
- private lateinit var titlebarBinding: TitlebarBinding
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- binding = ActivityMainBinding.inflate(layoutInflater)
- titlebarBinding = TitlebarBinding.bind(binding.root)
- setContentView(binding.root)
- titlebarBinding.title.text = "Title"
- titlebarBinding.back.setOnClickListener {
- }
- titlebarBinding.done.setOnClickListener {
- }
- }
-
- }