Android view获取方式演进

一、findViewById

缺点:代码量大,繁琐

二、butterknife

缺点:组件化开发中使用不友好(注意事项:https://blog.csdn.net/yufumatou/article/details/109583839

三、kotlin-android-extensions

优点:最简单,只需通过id即可

缺点:

1、只能支持Kotlin语言,而无法支持Java语言

2、在Recyclerview适配器中需要避免入坑

class OrderAdapter(val orderList: List<Order>) : RecyclerView.Adapter<OrderAdapter.ViewHolder>() {

    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.order_item, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val order = orderList[position]
        holder.itemView.tvOrderId.text = order.id
    }

    override fun getItemCount() = orderList.size
}

以上是错误用法,因为holder.itemView.tvOrderId反编译成java代码会看到每次都调用findViewById来获取控件,这样就失去ViewHolder无需重复获取控件的意义,这里正确写法如下:

class OrderAdapter(val orderList: List<Order>) : RecyclerView.Adapter<OrderAdapter.ViewHolder>() {

    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view){
       //需要在这里获取控件,防止重复findViewById
	   val tvOrderId: TextView = itemView.tvOrderId
	}

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.order_item, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val order = orderList[position]
        holder.tvOrderId.text = order.id
    }

    override fun getItemCount() = orderList.size
}

3、kotlin-android-extensions插件已被废弃

四、ViewBinding

1、Android studio 3.6及以上版本

2、build.gradle中如下配置(开启该配置后,创建布局文件,自动创建对于的Binding类)

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

3、activity中使用

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.textView.text = "Hello Word"
    }

}

4、fragment中使用

class MainFragment : Fragment() {

    private var mBinding: FragmentMainBinding? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        FragmentMainBinding.inflate(inflater, container, false).let{
		    mBinding = it
		    return it.root
		}
    }
	
	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
	    mBinding?.textView.text = "Hello"
	}

    override fun onDestroyView() {
        super.onDestroyView()
        mBinding = null
    }
}

5、adapter中使用

class OrderAdapter(val orderList: List<Order>) : RecyclerView.Adapter<OrderAdapter.ViewHolder>() {

    inner class ViewHolder(binding: OrderItemBinding) : RecyclerView.ViewHolder(view){
	   val tvOrderId: TextView = binding.tvOrderId
	}

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = OrderItemBinding(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val order = orderList[position]
        holder.tvOrderId.text = order.id
    }

    override fun getItemCount() = orderList.size
}

6、include中使用

(1)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 
        android:id="@+id/titleBar"
        layout="@layout/titlebar" />
    ...
</LinearLayout>

(2)使用include中控件

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 = "标题"
    }
}

7、merge中使用

(1)创建merge

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp" />
</merge>

(2)使用merge

<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>

(3)关联merge

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 = TitlebarBinding.bind(binding.root)
        setContentView(binding.root)
        titlebarBinding.title.text = "标题"
    }
}

五、DataBinding(参考DataBinding详解

六、总结

对比这几种方式,还是kotlin-android-extensions代码更为简洁,但具体使用根据项目而定,这里主要是学会各个方式,方便维护已有项目。

猜你喜欢

转载自blog.csdn.net/yufumatou/article/details/113122325