本文介绍: ViewBinding是Google在2019年I/O大会上公布的一款Android视图绑定工具,在Android Studio 3.6中添加一个功能,更准确的说,它是DataBinding一个轻量变体。还有在Adapter中的使用,因为布局不是只创建一次,而是每个item都会创建,不能像上面那样在Adapter里写一个binding全局变量,不然binding只会得到最后一次创建视图。另一个变量用于避免使用!您可以需要高级功能布局使用数据绑定,而在不需要高级功能布局中使用视图绑定

ViewBinding

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

使用方法

1.build.gradle中开启

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

android {
   ...
    buildFeatures {
        viewBinding true
    }
}

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

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

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

<LinearLayout
    ...
    tools:viewBindingIgnore="true" >
    ...
</LinearLayout>

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)
        // mtvxml定义的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<String>) : RecyclerView.Adapter<TextAdapter.TextViewHolder>() {
  
  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来获取,例如:

<?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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.appcompat.widget.Toolbar
        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" />
    
</androidx.constraintlayout.widget.ConstraintLayout>
<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include
        android:id="@+id/appbar"
        layout="@layout/app_bar"
        app:layout_constraintTop_toTopOf="parent" />
    
</androidx.constraintlayout.widget.ConstraintLayout>
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: MainLayoutBinding = MainLayoutBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setSupportActionBar(binding.appbar.toolbar)
        //不多说
    }

View Binding 的传统使用方式

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

class MainActivity : AppCompatActivity() {
    private val binding by viewBinding(ActivityMainBinding::inflate)
}

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

findViewById的区别

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

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

与DataBinding的对别

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

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

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

原文地址:https://blog.csdn.net/weixin_73871834/article/details/134695694

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_7651.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注