View binding makes it easier to write code that interacts with views. After view binding is enabled in a module, a binding class is generated for each XML layout file in that module. Instances of the binding class contain direct references to all views that have ids in the corresponding layout. In most cases, view binding replaces findViewById. 1.1 Setting Description View binding can be enabled by module. To enable viewBinding in a module, add a viewBinding element to its build.gradle file, as shown in the following example:
buildTypes {
...
android.buildFeatures {
viewBinding = true
}
}
Copy the code
If you want to ignore a layout file when generating binding classes, add the Tools :viewBindingIgnore=”true” attribute to the root view of the corresponding layout file:
<LinearLayout
...
tools:viewBindingIgnore="true" >
...
</LinearLayout>
Copy the code
1.2 Usage When view binding is enabled for a module, a binding class is generated for each XML layout file contained in the module. Each binding class contains references to the root view as well as all views with ids. The system generates the name of the Binding class by converting the name of the XML file to camel case and adding the word “Binding” to the end. For example, suppose a layout file is named result_profile.xml:
<LinearLayout ... >
<TextView android:id="@+id/name" />
<ImageView android:cropToPadding="true" />
<Button android:id="@+id/button"
android:background="@drawable/rounded_button" />
</LinearLayout>
Copy the code
The name of the generated binding class is ResultProfileBinding. This class has two fields: a TextView named Name and a button named Button. The ImageView in this layout has no ID, so there is no reference to it in the binding class. Each binding class also contains a getRoot() method that provides a direct reference to the root view of the corresponding layout file. In this example, the getRoot() method in the ResultProfileBinding class returns the LinearLayout root view. The following sections describe the use of generated binding classes in activities, Fragments, and Dialog. To set up an instance of the binding class for your Activity to use, perform the following steps in the Activity onCreate() method:
- Invoke the static inflate() method contained in the generated binding class. This action creates an instance of the binding class for the Activity to use.
- Get a reference to the root view by calling the getRoot() method or using the Kotlin attribute syntax.
- Pass the root view to setContentView() to make it the active view on the screen.
binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }
Copy the code
To set an instance of a binding class for your Fragment to use, perform the following steps in the onCreateView() method of the Fragment:
- Invoke the static inflate() method contained in the generated binding class. This creates an instance of the bound class for use by the Fragment.
- Get a reference to the root view by calling the getRoot() method or using the Kotlin attribute syntax.
- Return the root view from the onCreateView() method, making it the active view on the screen.
private var _binding: ResultProfileBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup? , savedInstanceState: Bundle? ) : View? { _binding = ResultProfileBinding.inflate(inflater, container, false) val view = binding.root return view } override fun onDestroyView() { super.onDestroyView() _binding = null }Copy the code
You can now use an instance of the bound class to reference any view:
binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }
Copy the code
To set up an instance of the binding class for your Fragment to use, perform the following steps in the Fragment onCreateView() method:
- Invoke the static inflate() method contained in the generated binding class. This action creates an instance of the bound class for the Dialog to use.
- Get a reference to the root view by calling the getRoot() method or using the Kotlin attribute syntax.
- Return the root view from the onCreate() method, making it the active view on the screen.
override fun onCreate(savedInstanceState: Bundle?) {
binding = DialogAppBinding.inflate(layoutInflater)
setContentView(binding.root)
}
Copy the code
To set an instance of a binding class for use by the Fragment, perform the following steps in the Fragment onCreateView() method:
- Invoke the static inflate() method contained in the generated binding class. This creates an instance of the binding class for the Adapter to use.
- Get a reference to the root view by calling the getRoot() method or using the Kotlin attribute syntax.
- Returns the root view from the onCreateViewHolder(parent: ViewGroup, viewType: Int) method, making it the active view on the screen.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return AudioListViewHolder(
GaItemAudioLayoutBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
Copy the code
1.2.5 Using View Binding in A View This section uses EmptyView as an example
View.inflate(context, R.layout.ui_empty_view_layout, Above this, / / instead of val binding = UiEmptyViewLayoutBinding. Inflate (LayoutInflater. The from (mContext), this, true)Copy the code
The merge tag does not contain the merge tag. You need to add an ID to the include tag. The usage is as follows.
<include android:id="@+id/include" layout="@layout/layout_include_item" /> val binding: ActivityMainBinding = ActivityMainBinding. Inflate (layoutInflater) binding. Include. IncludeTvTitle. SetText (" use the include Controls in layout, not including merge")Copy the code
Merge the include tag with the merge tag. Note that this is not the same as DataBinding. Add the id to the include tag.
<include layout="@layout/layout_merge_item" /> val binding: ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater) val mergeItemBinding = LayoutMergeItemBinding. Bind (binding. Root) mergeItemBinding. MergeTvTitle. SetText (" use the include layout of controls, including the merge ")Copy the code
In Android Studio 4.2.0 Bata 2, it is not possible to use the ViewStub tag directly in the ViewBinding layout as of the time of this article. Only use in DataBinding layout (with layout label), see the issue stackoverflow.com/questions/5… Since there is no authoritative data to prove it, I suggest you try it directly in the project Binding. If you have other implementation methods in the ViewBinding layout, please leave a message and let me know
Since EmptyView is optional, there is no abstract method definition here
Public GAEmptyView getPageEmptyView() {return null; } public void setPageLoading() { if (getPageEmptyView() ! = null) { getPageEmptyView().setLoading(); } } public void setPageLoadSuccess() { if (getPageEmptyView() ! = null) { getPageEmptyView().setLoadSuccess(); } } public void setPageLoadFailed() { if (getPageEmptyView() ! = null) { getPageEmptyView().setLoadFailed(); } } public void setPageEmpty() { if (getPageEmptyView() ! = null) { getPageEmptyView().setEmpty(); Public void setPageRecipeEmpty() {} public void setPageEmptyViewStatus(EmptyStatus status) {if (getPageEmptyView() ! = null) { switch (status) { case LOADING: setPageLoading(); break; case LOAD_SUCCESS: setPageLoadSuccess(); break; case LOAD_FAILED: setPageLoadFailed(); break; case EMPTY: setPageEmpty(); break; case RECIPE_EMPTY: setPageRecipeEmpty(); break; Default: // TODO: 2020/12/15 unknown break; }}}Copy the code
2.2.1 Relying on the base class GABaseBindingActivity
abstract class GABaseBindingActivity<VB : ViewBinding> : GABaseActivity() { protected var _binding: VB? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) _binding = getBinding() _binding? .let { setContentView(it.root) }? :let {log. d("Warning","getBinding() is empty, please configure ViewBinding if necessary ")}} abstract fun getBinding(): VB}Copy the code
2.2.2 The reason for not relying on base class encapsulation requires some basic knowledge of principles and kotlin syntax
inline fun <reified VB : ViewBinding> inflateBinding(layoutInflater: LayoutInflater) =
VB::class.java.getMethod("inflate", LayoutInflater::class.java)
.invoke(null, layoutInflater) as VB
inline fun <reified VB : ViewBinding> Activity.inflate() = lazy {
inflateBinding<VB>(layoutInflater).apply { setContentView(root) }
}
inline fun <reified VB : ViewBinding> Dialog.inflate() = lazy {
inflateBinding<VB>(layoutInflater).apply { setContentView(root) }
}
Copy the code