赞
踩
初级菜鸟,正在向中级菜鸟努力!
刚刚接触Android开发,有好多东西都不太懂,又喜欢忘东西,干脆写博客记录一下吧。
目录
kotlin-android-extensions插件已被废弃,现在推荐使用ViewBinding来进行替代。我的理解是,viewBinding是我们在完成创建一个layout的xml文件时自动生成的一个绑定类,该类以创建的xml文件名+Binding来命名且采用驼峰命名法,如果xml文件名是activity_main.xml,那么绑定类的名称就是ActivityMainBinding,我们可以通过实例化这个绑定类来操纵xml布局文件中的控件属性。以下是viewBinding的简单用法:
在Module级别的build.gradle中写入如下代码:
- android {
- ...
- buildFeatures {
- viewBinding true
- }
- }
我们使用MainActivity为例,使用viewBinding来引入activity_main.xml这个布局,实例化这个绑定类为binding,然后就可以使用其中的控件了,这里我们将根布局传入setContentView中代替原来的R.layout.activity_main。我们可以先全局声明一下,在oncreate方法中进行赋值,这样就不用在MainActivity中的其他方法中使用view Binding时重新创建实例了。
- class MainActivity : AppCompatActivity() {
- lateinit var binding: ActivityMainBinding
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- binding=ActivityMainBinding.inflate(layoutInflater)
- setContentView(R.layout.activity_main)
- }
- }
假设我们有一个布局文件叫fragment_main.xml,并且想在MainFragment中去显示这个布局。因为kotlin的判空机制,所以代码有些怪怪的。
- 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
- }
-
- }

最核心的逻辑仍然是调用FragmentMainBinding的inflate()函数去加载fragment_main.xml布局文件,但由于这是在Fragment当中,所以使用了3个参数的inflate()函数重载,这和我们平时在Fragment中去加载布局文件的方式如出一辙。而在onCreateView()函数中加载的布局,在与其对应的onDestroyView()函数中对binding变量置空,以保证binding变量的有效生命周期是在onCreateView()函数和onDestroyView()函数之间。
这是《第一行代码》中的适配器部分,使用viewBinding改造后的样子。首先改造ViewHolder,让其构造函数接收FruitItemBinding这个参数。但是注意,ViewHolder的父类RecyclerView.ViewHolder它只会接收View类型的参数,因此我们需要调用binding.root获得fruit_item.xml中根元素的实例传给RecyclerView.ViewHolder。
- class FruitAdapter(val fruitList: List<Fruit>) : RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
-
- 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

主要的改动在ViewHolder和onCreateViewHolder中,其他的 部分并没有改变!
假设我们引入的布局如下:
- <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布局文件中引入布局可以这么写:
- <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>
一定要记得给include的布局加上id属性,不然到MainActivity中就找不到了!!
最后在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>

与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中的代码如下:
- 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 {
- }
- }
-
- }

我们创建了两个viewBinding,一个是activity_main.xml的,另一个是我们引入的merge标签的,然后使用merge标签自动生成的viewBinding的bind方法绑定到activity_main.xml的viewBinding中。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。