preface

ByteCode, dedicated to share the latest technology original articles, involving Kotlin, Jetpack, translation, system source code, LeetCode/point Offer/multithreading/domestic and foreign large factory algorithm problems and so on a series of articles.

First of all, I wish you a happy New Year. 2020 will be an extraordinary year. 2021 will be a new starting point for you and me.

2021 New signature: More code, more articles.

The first article in 2021 complements the last article in late 2020 with the end of the Kotlin plugin and the rise of ViewBinding.

In the last article on the Kotlin plugin, the rise of ViewBinding, I explained why Google does not recommend using Synthetic views in projects. Google suggests using ViewBinding instead of the Kotlin composition method. What is the difference between ViewBinding and DataBinding?

ViewBinding:

  • Only binding views are supported
  • You do not need to add layout labels to the layout file
  • Needs to be at the module levelbuild.gradleAdd to fileviewBinding = trueYou can use
  • It is more efficient than DataBinding because it avoids the overhead and performance issues associated with DataBinding
  • Compared to thekotlin-android-extensionsThe plug-in avoids null exceptions

DataBinding:

  • Contains all the functionality of ViewBinding
  • Needs to be at the module levelbuild.gradleIn-file adddataBinding = trueYou need to add the Layout label to the layout file to use it
  • Support data and view bidirectional binding
  • It is less efficient than ViewBinding because the annotation handler affects the build time of the data binding.

ViewBinding can be implemented, DataBinding can be implemented, but DataBinding is less performance than ViewBinding. DataBinding and ViewBinding generate bound classes for each XML file.

R.layout.activity_main -> ActivityMainBinding
R.layout.fragment_main -> FragmentMainBinding
R.layout.dialog_app -> DialogAppBinding
Copy the code

At the end of the Kotlin plugin, the rise of the ViewBinding article also analyzes the problems caused by the Kotlin synthesis method. Even though Kotlin’s synthesis method has many problems, there are still people willing to use it.

ViewBinding and DataBinding solve so many problems for us, but why many people do not want to use ViewBinding and DataBinding, today we will analyze from the perspective of use.

ViewBinding and DataBinding

I’ve roughly summarized all the uses of ViewBinding and DataBinding in different scenarios, so let’s look at how they can be used in a project.

The basic configuration

Gradle plug-ins have been built in since Android Studio 3.6. You don’t need to add any additional libraries to use them, but they are used differently in Android Studio 3.6 and Android Studio 4.0.

// Android Studio 3.6 Android {viewBinding {enabled = true} dataBinding{enabled = true}} // Android Studio 4.0 android { buildFeatures { dataBinding = true viewBinding = true } }Copy the code

The use of ViewBinding

Because there are so many scenarios involved, I will only list the core parts to reduce space. If you have never used them before, just know that the ViewBinding threshold is higher than Kotlin’s compositing method.

Instead of generating a Binding class for a layout, add the following properties to the root view of the layout file

<LinearLayout tools:viewBindingIgnore="true" >
</LinearLayout>
Copy the code

Used in an Activity

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val binding: ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)
}
Copy the code

Use in fragments

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup? , savedInstanceState: Bundle?) : View { val binding = FragmentViewBindBinding.inflate(inflater,container,false) return binding.root }Copy the code

Use in Adapter

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    RecycleItemProductBinding.inflate(LayoutInflater.from(parent.context), parent, false)
}
Copy the code

Used in Dialog

override fun onCreate(savedInstanceState: Bundle?) {
    binding = DialogAppBinding.inflate(layoutInflater)
    setContentView(binding.root)
}
Copy the code

Use of the include tag

Merge labels do not contain merge labels. You need to add ids to include labels. 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

The merge tag contains the merge tag. Add an ID to the include tag. You can use the ID directly in DataBinding, but ViewBinding does not. The use of ViewBinding is shown below.

<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

ViewStub label usage

In Android Studio 4.2.0 Bata 2, the ViewStub tag cannot be used directly in the ViewBinding layout as of the time of this article. Can only be used in DataBinding layouts (with layout tags), see issue

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

The use of the DataBinding

Because there are so many scenarios involved, I’ll just list the core to save space. If you’ve never used it before, just know that DataBinding has a higher threshold than Kotlin composition.

You need to add a Layout label to the layout file

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <LinearLayout...>
    ...
    </LinearLayout
</layout>
Copy the code

Used in an Activity

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
    binding.lifecycleOwner = this
    setContentView(binding.root)
}
Copy the code

Use in fragments

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup? , savedInstanceState: Bundle?) : View { val binding = FragmentViewBindBinding.inflate(inflater,container,false) binding.lifecycleOwner = this return binding.root }Copy the code

Use in Adapter

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
    val bidning:RecycleItemProductBinding =  DataBindingUtil.bind(view) 
}
Copy the code

Used in Dialog

override fun onCreate(savedInstanceState: Bundle?) {
    binding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.dialog_data_binding, null, false)
    setContentView(binding.root)
}
Copy the code

Use of the include tag

The include tag does not contain the merge tag. You need to add an ID to the include tag.

<include android:id="@+id/includeData" layout="@layout/layout_include_data_item"/> val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.l ayout. Activity_main) binding. IncludeData. IncludeTvTitle. SetText (" through code sets include the layout of controls ")Copy the code

Merge the include tag with a ViewBinding tag. Add an ID to the include tag, which can be used directly in DataBinding, but not in ViewBinding.

<include android:id="@+id/includeDataMerge" layout="@layout/layout_merge_data_item"/> val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.l ayout. Activity_main) binding. IncludeDataMerge. MergeTvTitle. SetText (" through setting the merge code layout controls ")Copy the code

ViewStub label usage

Add an ID to the ViewStub tag, which can be used directly in DataBinding.

<ViewStub android:id="@+id/stub" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout="@layout/view_stub" /> binding.stub.setOnInflateListener { stub, inflated -> // ViewBinding val viewStub: ViewStubBinding = viewstubbinding.bind (vehicle) viewstub.tvtitle.settext (" Use viewStub to load ViewBinding layout ")} binding.stub.setOnInflateListener { stub, inflated -> // DataBinding val dataViewStub: ViewStubDataBinding = DataBindingUtil.bind(inflated)!! DataViewStub. TvTitle. SetText (" use ViewStub loading DataBinding layout ")} the if (! binding.stub.isInflated) { binding.stub.viewStub!! .inflate() }Copy the code

As you can see, in the Ativity, Fragment, Dialog, Adapter, Include, Merge, ViewStub, and so on, Using ViewBinding or DataBinding requires different processing, which is too high a threshold to use compared to the Kotlin synthesis method.

So is there a way to unify these initialization schemes so that DataBinding and ViewBinding can be implemented in Kotlin with just one line of code?

One line of code

If you need to manually do different processing in each scenario, the cost is very high, so I introduced a new library Binding, Binding combined with the Kotlin delegate property to encapsulate the DataBinding and ViewBinding different processing. A simple API is provided as shown below.

Use in ViewBinding

val binding: ActivityViewBindBinding by viewbind()
Copy the code

Use in DataBinding

Val binding: ActivityDataBindBinding by databind(r.layout.activity_data_bind) ActivityDataBindBinding by databind()Copy the code

As you can see, all of the above scenarios can be implemented with a few simple apis, but let’s first introduce Binding.

The future of Binding provides a general findViewById solution. As the technology iterates from Butterknife, DataBinding and Kotlin to ViewBinding, New technologies may emerge in the future. As long as the external use of Binding remains the same, migration can be completed by updating the Binding, no matter how technology changes.

BindingHas the following advantages:

  • Provides a lot of actual combat cases includedAtivityFragmentDialogAdapterincludemergeViewStubNavigation, two-way data binding, and so on
  • A simple API requires only one line of code to implement DataBinding or ViewBinding
  • Support inActivityAppCompatActivityFragmentActivityFragmentDialogUse DataBinding or ViewBinding in
  • Support inListAdapterPagedListAdapterPagingDataAdapterRecyclerView.AdapterUse DataBinding or ViewBinding in
  • Support in Navigaion fragments management framework, BottomSheetDialogFragment use DataBinding and ViewBinding scenario
  • Avoid lots of template code
  • Avoid memory leaks and have life cycle awareness when the life cycle is inonDestroyed()Will automatically destroy data

Let’s take a look at how Binding can be used in a project by adding the following code to the build.gradle file at the module level and enabling DataBinding or ViewBinding.

Dependencies {implementation 'com. Hi - DHL :binding:1.0.7}Copy the code

To use this in activities, appactivity, FragmentActivity, add either by viewbind() or by databind(r.layout.activity_main), as shown in the following example.

class MainActivity : AppCompatActivity() {

    // DataBinding
    val binding: ActivityMainBinding by databind(R.layout.activity_main)
    
    // ViewBinding
    val binding: ActivityMainBinding by viewbind()
}
Copy the code

Two methods are available in fragments:

  • Method 1: inonCreateViewThis method is applicable to all applicationsFragmentThe scene of
  • Method two: inonViewCreatedThe use of

A:

class FragmentNav1 : Fragment(R.layout.fragment_main) {
    
    // DataBinding
  	val binding: FragmentMainBinding by databind()
    
    // ViewBinding
  	 val binding: FragmentMainBinding by viewbind()
  
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return binding.root
    }
}
Copy the code

In mode two, the following points should be paid attention to:

  • Not in theNavigaion FragmentBottomSheetDialogFragmentThe use of
  • In other Fragment scenarios, ifWay 2The interface is not displayedMethods aCan solve
class FragmentNav1 : Fragment(R.layout.fragment_main) {
    
    // DataBinding
  	val binding: FragmentMainBinding by databind()
    
    // ViewBinding
  	 val binding: FragmentMainBinding by viewbind()
  
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.apply { textView.setText("Binding") }
    }
}
Copy the code

Use in Dialog as follows.

class AppDialog(context: Context) : Dialog(context, R.style.AppDialog) {

    // DataBinding
    val binding: DialogAppBinding by databind(R.layout.dialog_data_binding)
    
    // ViewBinding
    val binding: DialogAppBinding by viewbind()
}
Copy the code

Or add a life-cycle aware Dialog.

class AppDialog(context: Context,lifecycle: Lifecycle) : Dialog(context, r.style.appDialog) {// DataBinding monitor life cycle val binding: DialogAppBinding by databind(r.layout. dialog_data_binding, lifecycle) // ViewBinding DialogAppBinding by viewbind(lifecycle) }Copy the code

To use DataBinding and ViewBinding within the Adapter, simply add by Viewbind () or by Databind () to the ViewHolder, as shown in the following example.

class ProductViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    
    // DataBinding
    val binding: RecycleItemProductBinding by databind()

    // ViewBinding
    val binding: RecycleItemProductHeaderBinding by viewbind()

}
Copy the code

Extension method to support binding of data during DataBinding initialization.

val binding: ActivityDataBindBinding by databind(R.layout.activity_data_bind) {
    val account = Account()
    account.name = "test"
    this.account = account
}
Copy the code

The above are just a few common uses, but there are many more examples (include, Merge, ViewStub, Navigation, data bidirectional Binding, etc.) that have been uploaded to GitHub.

GitHub Repository: github.com/hi-dhl/Bind…

This article complements the Kotlin plugin and the rise of ViewBinding, analyzing the differences between DataBinding and ViewBinding in terms of usage. It also showed you how to implement DataBinding and ViewBinding in a simpler way.

This is the end of the article, if it is helpful to give me a thumbs up is the biggest encouragement

More code, more articles

Welcome to the public account: ByteCode, continue to share the latest technology


Finally, I recommend the projects and websites I have been updating and maintaining:

  • New video series: Modern Android Development (MAD) Tips series: View online

  • Androidx-jetpack-practice androidX-Jetpack-practice androidX-Jetpack-Practice androidX-Jetpack-Practice AndroidX-Jetpack-Practice

  • LeetCode/multiple thread solution, language Java and Kotlin, including a variety of solutions, problem solving ideas, time complexity, spatial complexity analysis

    • Job interview with major companies at home and abroad
    • LeetCode: Read online
  • Android10 Source code Analysis series of articles, understand the system Source code, not only help to analyze the problem, in the interview process, is also very helpful to us, the warehouse continues to update, welcome to check android10-source-Analysis

  • Collate and translate a series of selected foreign Technical articles, each Article will have a translator’s thinking part, a more in-depth interpretation of the original text, the warehouse continues to update, welcome to visit the Technical-Article-Translation

  • “Designed for Internet people, navigation of domestic and foreign famous stations” includes news, sports, life, entertainment, design, product, operation, front-end development, Android development and so on. Welcome to check the navigation website designed for Internet people

Article history

  • Kotlin’s Technique and Principle Analysis that few people know (1)
  • Kotlin’s Technique and Principle Analysis that few people know (II)
  • AndroidX App Startup practice and principle analysis of Jetpack’s latest member
  • Jetpack member Paging3 Practice and Source Code Analysis (PART 1)
  • Jetpack Member Paging3 Network Practice and Principle Analysis (II)
  • Jetpack member Paging3 retrieves network page data and updates it to the database
  • Jetpack member Hilt practice (1) Start a pit
  • Jetpack member Hilt with App Startup (ii) Advanced article
  • New member of Jetpack Hilt and Dagger are very different
  • All aspects of Hilt and Koin performance were analyzed
  • PokemonGo Jetpack + MVVM minimalism
  • What is Kotlin Sealed? Why does Google use them all
  • Kotlin StateFlow search features practice DB + NetWork
  • Bye-bye buildSrc, embrace Composing builds for faster Android builds
  • [Google] Bye SharedPreferences embrace Jetpack DataStore
  • Google is asking whether it should learn from Kotlin
  • An interesting new version of Android Studio has been announced
  • The end of the Kotlin plugin and the rise of ViewBinding