Android View Binding的使用
轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/zhaoyanjun6/article/details/120751996
本文出自【趙彥軍的博客】
文章目錄
- 什么是View Binding
- 如何啟用View Binding 功能
- 怎么去使用View Binding
- Activity 綁定視圖
- Fragment 綁定視圖
- 使用View Binding 寫的基類
- 1、通過(guò)反射的方式(這種方式不推薦使用,會(huì)有混淆問(wèn)題)
- 2、不通過(guò)反射的方式
- RecyclerView ViewHolder 使用
什么是View Binding
View Binding是Android Studio 3.6推出的新特性,目的是為了替代findViewById(內(nèi)部實(shí)現(xiàn)還是使用findViewById)。。在啟動(dòng)視圖綁定后,系統(tǒng)會(huì)為改模塊中的每個(gè)xml文件生成一個(gè)綁定類,綁定類的實(shí)例包含對(duì)在相應(yīng)布局中具有 ID 的所有視圖的直接引用。
View Binding 的優(yōu)點(diǎn)
- Null 安全:由于視圖綁定會(huì)創(chuàng)建對(duì)視圖的直接引用,因此不存在因視圖 ID 無(wú)效而引發(fā) Null 指針異常的風(fēng)險(xiǎn)。此外,如果視圖僅出現(xiàn)在布局的某些配置中,則綁定類中包含其引用的字段會(huì)使用 @Nullable 標(biāo)記。
- 類型安全:每個(gè)綁定類中的字段均具有與它們?cè)?XML 文件中引用的視圖相匹配的類型。這意味著不存在發(fā)生類轉(zhuǎn)換異常的風(fēng)險(xiǎn)。
如何啟用View Binding 功能
android {buildFeatures {viewBinding true} }如果想在生成綁定類時(shí)忽略某個(gè)布局文件,將 tools:viewBindingIgnore="true" 屬性添加到相應(yīng)布局文件的根視圖中:
<?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"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:viewBindingIgnore="true"tools:context=".MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>怎么去使用View Binding
為用視圖綁定功能后,系統(tǒng)會(huì)為該模塊中包含的每個(gè) XML 布局文件生成一個(gè)綁定類。這個(gè)類的類名是以xml布局文件名去掉下?lián)Q線后,單詞首字母大寫加上Binding命名的。如 activity_main.xml生成的類 ActivityMainBinding.
Activity 綁定視圖
-
第一步:調(diào)用生成的綁定類中包含的靜態(tài) inflate() 方法。此操作會(huì)創(chuàng)建該綁定類的實(shí)例以供 Activity 使用。
-
第二步:通過(guò)調(diào)用 getRoot() 方法或使用 Kotlin 屬性語(yǔ)法獲取對(duì)根視圖的引用。
-
第三步:將根視圖傳遞到 setContentView(),使其成為屏幕上的活動(dòng)視圖。
使用:
class MainActivity : AppCompatActivity() {lateinit var binding: ActivityMainBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)//關(guān)鍵代碼binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)//獲取控件binding.tv.setOnClickListener {Toast.makeText(this, "hahha", Toast.LENGTH_SHORT).show()}} }Fragment 綁定視圖
如何在 Fragment 中使用視圖綁定 請(qǐng)?jiān)?Fragment 的 onCreateView()方法中執(zhí)行以下步驟(注意:Fragment 的存在時(shí)間比其視圖長(zhǎng)。請(qǐng)務(wù)必在 Fragment 的 onDestroyView() 方法中清除對(duì)綁定類實(shí)例的所有引用。)
-
調(diào)用生成的綁定類中包含的靜態(tài) inflate() 方法。此操作會(huì)創(chuàng)建該綁定類的實(shí)例以供 Fragment 使用。
-
通過(guò)調(diào)用 getRoot() 方法或使用 Kotlin 屬性語(yǔ)法獲取對(duì)根視圖的引用。
-
從 onCreateView() 方法返回根視圖,使其成為屏幕上的活動(dòng)視圖
在onViewCreated中使用View Binding
//在onViewCreated中使用View Binding public class MyFragment extends Fragment {private FragmentMyBinding binding;public MyFragment() {}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {return inflater.inflate(R.layout.fragment_my,container,false);}@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);FragmentMyBinding binding = FragmentMyBinding.bind(view);this.binding = binding;binding.textView.setText("這是Fragment");binding.button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Log.d("Fragment", "點(diǎn)擊了按鈕");}});}@Overridepublic void onDestroy() {super.onDestroy();binding = null;}使用View Binding 寫的基類
1、通過(guò)反射的方式(這種方式不推薦使用,會(huì)有混淆問(wèn)題)
Activity 基類設(shè)計(jì)
//Java public class BaseActivity<T extends ViewBinding> extends AppCompatActivity {protected T viewBinding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();Class cls = (Class) type.getActualTypeArguments()[0];try {Method inflate = cls.getDeclaredMethod("inflate", LayoutInflater.class);viewBinding = (T) inflate.invoke(null, getLayoutInflater());setContentView(viewBinding.getRoot());} catch (NoSuchMethodException | IllegalAccessException| InvocationTargetException e) {e.printStackTrace();}} }//使用public class MainActivity extends BaseActivity<ActivityMainBinding> {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);viewBinding.button.setText("這是 MainActivity ViewBinding");viewBinding.button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Log.d("MainView","點(diǎn)擊按鈕");}});} } //Kotlin open class BaseActivity<T : ViewBinding> : AppCompatActivity() {protected lateinit var binding: Toverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val type = javaClass.genericSuperclass as ParameterizedTypeval aClass = type.actualTypeArguments[0] as Class<*>val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java)binding = method.invoke(null, layoutInflater) as TsetContentView(binding.root)} }class MainActivity : BaseActivity<ActivityMainBinding>() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding.textView.text = "這是MainActivity"} }Fragment 基類設(shè)計(jì)
//Java public class BaseFragment<T extends ViewBinding> extends Fragment {protected T viewBinding;@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();Class cls = (Class) type.getActualTypeArguments()[0];try {Method inflate = cls.getDeclaredMethod("inflate", LayoutInflater.class, ViewGroup.class, boolean.class);viewBinding = (T) inflate.invoke(null, inflater, container, false);} catch (NoSuchMethodException | IllegalAccessException| InvocationTargetException e) {e.printStackTrace();}return viewBinding.getRoot();} }//使用 public class MainFragment extends BaseFragment<FragmentMainBinding>{@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);viewBinding.button.setText("這是 MainFragment ViewBinding");viewBinding.button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Log.d("MainView","點(diǎn)擊按鈕");}});} } //Kotlin open class BaseFragment<T:ViewBinding>:Fragment(){lateinit var binding: Toverride fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {val type = javaClass.genericSuperclass as ParameterizedTypeval aClass = type.actualTypeArguments[0] as Class<*>val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java,ViewGroup::class.java,Boolean::class.java)binding = method.invoke(null,layoutInflater,container,false) as Treturn binding.root} }class FirstFragment : BaseFragment<FragmentFirstBinding>() {override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)binding.textView.text = "這是FirstFragment"} }2、不通過(guò)反射的方式
Activity 基類設(shè)計(jì)
abstract class BaseActivity<T : ViewBinding> : AppCompatActivity() {private lateinit var _binding: Tprotected val binding get() = _binding;override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)_binding = getViewBinding()setContentView(_binding.root)}protected abstract fun getViewBinding(): T }class MainActivity : BaseActivity<ActivityMainBinding>() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding.textView.text = "這是MainActivity"}override fun getViewBinding() = ActivityMainBinding.inflate(layoutInflater) }Fragment 基類設(shè)計(jì)
abstract class BaseFragment<T : ViewBinding> : Fragment() {private lateinit var _binding: Tprotected val binding get() = _binding;override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {_binding = getViewBinding(inflater, container)return _binding.root}protected abstract fun getViewBinding(inflater: LayoutInflater, container: ViewGroup?): T }class FirstFragment : BaseFragment<FragmentFirstBinding>() {override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)binding.textView.text = "這是FirstFragment"}override fun getViewBinding(inflater: LayoutInflater,container: ViewGroup?) = FragmentFirstBinding.inflate(inflater, container, false) }RecyclerView ViewHolder 使用
方式一:
lass MyItemRecyclerViewAdapter(private val values: List<PlaceholderItem> ) : RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {return ViewHolder(FragmentItemBinding.inflate(LayoutInflater.from(parent.context),parent,false))}override fun onBindViewHolder(holder: ViewHolder, position: Int) {val item = values[position]holder.idView.text = item.idholder.contentView.text = item.content}override fun getItemCount(): Int = values.sizeclass ViewHolder(binding: FragmentItemBinding) : RecyclerView.ViewHolder(binding.root) {val idView: TextView = binding.itemNumberval contentView: TextView = binding.content}}方式二:
class MyItemRecyclerViewAdapter(private val values: List<PlaceholderItem> ) : RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {return ViewHolder(FragmentItemBinding.inflate(LayoutInflater.from(parent.context),parent,false))}override fun onBindViewHolder(holder: ViewHolder, position: Int) {val item = values[position]holder.binding.itemNumber.text = item.id}override fun getItemCount(): Int = values.sizeclass ViewHolder(val binding: FragmentItemBinding) : RecyclerView.ViewHolder(binding.root)} 與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Android View Binding的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java线程安全Lock、Reentra
- 下一篇: Java队列 Queue