Jetpack series (8) – Data Binding && View Binding

A brief introduction to Hilt

First impression

Data Binding, including all View Binding functions, support bidirectional Binding

View Binding only supports Binding views, an alternative to the Kotlin-Android-Extensions plugin

Data Binding and View Binding can exist together

Data Binding performance is inferior to View Binding, so some projects only use View Binding

The basic concept

I’m just going to use a View Binding instead of findViewById(), Data Binding

The basic use

View Binding basic use

  1. willviewBindingElement to whichbuild.gradleIn the file
android {
    ...
    viewBinding {
        enabled = true}}Copy the code
  1. Use view bindings in your Activity

    • In the ActivityonCreate()Method to call the static contained in the generated binding classinflate()methods
    • withBinding. The control IdOperating controls
    // MainActivity
    class MainActivity : AppCompatActivity() {
        private lateinit var binding: ActivityMainBinding
        
        override fun onCreate(savedInstanceState: Bundle?). {
            super.onCreate(savedInstanceState)
            // Automatically generated
            binding = ActivityMainBinding.inflate(layoutInflater)
            setContentView(binding.root)
        }    
    }
    Copy the code
  2. Use view binding in fragments

    • Please in fragmentsonCreateView()Method, calling the static contained in the generated binding classinflate()methods
    class DeepLinkFragment : Fragment() {
    
        private var _binding: FragmentDeepLinkBinding? = null
        private val binding
            get() = _binding!!
    
        private val mainViewModel: MainViewModel by activityViewModels()
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup? , savedInstanceState:Bundle?).: View {
            _binding = FragmentDeepLinkBinding.inflate(inflater, container, false)
            return binding.root
        }
     
        override fun onDestroy(a) {
            super.onDestroy()
            _binding = null}}Copy the code
  3. Use ViewBinding in Adapter

    • By binding classesinflateMethods the incomingViewHolder
    // WordListAdapter.kt
    class WordListAdapter : ListAdapter<Word, WordViewHolder>(WORDS_COMPARATOR) {
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WordViewHolder =
            WordViewHolder.create(parent)
    
        override fun onBindViewHolder(holder: WordViewHolder, position: Int) {
            val item = getItem(position)
            holder.bind(item)
        }
    
        companion object {
            private val WORDS_COMPARATOR = object : DiffUtil.ItemCallback<Word>() {
                override fun areItemsTheSame(oldItem: Word, newItem: Word): Boolean =
                    oldItem == newItem
    
                override fun areContentsTheSame(oldItem: Word, newItem: Word): Boolean =
                    oldItem.word == newItem.word
    
            }
        }
    
    }
    
    class WordViewHolder(binding: ItemWordBinding) : RecyclerView.ViewHolder(binding.root) {
    
        private val textView: TextView = binding.textView
    
        fun bind(word: Word?).{ textView.text = word? .word? :""
        }
    
        companion object {
            fun create(parent: ViewGroup): WordViewHolder {
                val binding =
                    ItemWordBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                return WordViewHolder(binding)
            }
        }
    }
    Copy the code

Data Binding basic use

  1. Modify the build.gradle file

    dataBinding {
        enabled = true
    }
    Copy the code
  2. Generate the data Binding layout, see Point 3

    • I’m going to do a refresh effect here
    • Click on the eventonClick="@{()-> model.updateTaps()}"
    
            
    <layout 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">
    
        <data>
            <variable
                name="model"
                type="com.huang.myapplication.viewmodel.MainViewModel" />
        </data>
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/home_contain"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".ui.main.home.HomeFragment">
     
            <Button
                android:id="@+id/btn_add"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginStart="10dp"
                android:layout_marginTop="10dp"
                android:layout_marginEnd="10dp"
                android:text="@string/refresh"
                android:onClick="@{()-> model.updateTaps()}"
                app:layout_constraintHorizontal_weight="1"
                app:layout_constraintLeft_toRightOf="@+id/btn_next"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
    
            <TextView
                android:id="@+id/tv_count"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:text="@{model.taps}"
                app:layout_constraintBottom_toBottomOf="@+id/tv_current_count"
                app:layout_constraintLeft_toRightOf="@+id/tv_current_count"
                app:layout_constraintTop_toTopOf="@+id/tv_current_count" />
    
     
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>
    Copy the code
  3. Look at the data in the viewModel

    class MainViewModel @Inject constructor(
        private val repository: WordRepository
    ) : ViewModel() {
    
        private var _tapCount = 0
        private var _taps = MutableLiveData<String>("$_tapCount taps")
       
        val taps: LiveData<String> =  _taps
    
        fun updateTaps(a) {
            _tapCount++
            _taps.value = "$_tapCount taps"}}Copy the code
  4. Binding view

    • The Activity generates the Binding view class

       // Method 1:
       val binding: ActivityXxxBinding = DataBindingUtil.setContentView(
           this, R.layout.activity_main)
      
       // Method 2:
       val binding: ActivityXxxBinding = ActivityMainBinding.inflate(getLayoutInflater())
      Copy the code
    • Use data binding items in Fragment, ListView, or RecyclerView adapters

      // Method 1:
      val listItemBinding = ListItemBinding.inflate(layoutInflater, viewGroup, false)
      
      // Method 2:
      val listItemBinding = DataBindingUtil.inflate(layoutInflater,R.layout.list_item, viewGroup, false)
      Copy the code
    • You can use LiveData objects as data binding sources to automatically notify the interface of data changes, requiring binding.lifecycleOwner = this to set the lifecycle of the view-binding class

      class HomeFragment : Fragment() {
      
          private var _binding: FragmentHomeBinding? = null
          private val binding
              get() = _binding!!
      
          private lateinit var adapter: WordListAdapter
      
          private val mainViewModel: MainViewModel by activityViewModels()
      
          override fun onCreateView(
              inflater: LayoutInflater, container: ViewGroup? , savedInstanceState:Bundle?).: View {
              _binding = DataBindingUtil.inflate(layoutInflater, R.layout.fragment_home,container, false)
              setHasOptionsMenu(true)
              binding.lifecycleOwner = this
              return binding.root
          }
      
          override fun onDestroy(a) {
              super.onDestroy()
              _binding = null}}Copy the code

Related knowledge points

ViewBinding ignores files

  • Once ViewBinding is enabled, Android Studio automatically generates a Binding class for each layout file we write

  • The Binding class is named after the layout file is humped and ends with a Binding.

  • If there are layout files for which you do not want to generate a Binding class, you can add tools at the root of the layout file :viewBindingIgnore=”true”

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

Include layout in a View Binding

  • The View Binding uses an include to add an ID, which is searched by id

    <include
             android:id="@+id/includeTitle"
             layout="@layout/include_title" />/ / InOutFragment kt binding. IncludeTitle. ToolbarTitle. Text = "in operation"Copy the code

Quickly generate a Data Binding layout

  • alt + Enterchoosecover data to data binding layout

Binding expressions (Data Bindng)

  • Arithmetic operator+ - / * %
  • String concatenation operator+
  • Logical operator&& | |
  • Binary operator& | ^
  • Unary operator+ -! ~
  • Shift operator>> >>> <<
  • Comparison operator== > < >= <=(Please note that<Need to escape as<)
  • instanceof
  • Grouping operator(a)
  • Literal operators – characters, strings, numbers,null
  • Type conversion
  • The method call
  • Field access
  • Array access[]
  • Ternary operator? :

Data Binding

  • @ = {}The notation, which importantly contains the “=” symbol, receives data changes for attributes and listens for user updates at the same time

A link to the

Jetpack (1) – Navigation

Jetpack series (Ii) — Lifecycle

Jetpack series (3) – LiveData

Jetpack series (4) – ViewModel

Jetpack series (5) — Room

Jetpack series (6) – Paging3

Jetpack (7) – Hilt

The resources

A website

Website 2