Implementing Simple Data Binding

The next job is to hook up your RecyclerView. This is a job that you have done before. But this time, you will use data binding to speed up your work.

Data binding provides several benefits that make life easier when working with layouts. In simple cases, like the one you will see in this section, it allows you to access views without needing to call findViewById(…). Later, you will see more advanced uses of data binding, including how it helps you implement MVVM.

Start by enabling data binding and applying the kotlin-kapt plug-in in your app’s build.gradle file.

Listing 19.2  Enabling data binding (app/build.gradle)

apply plugin: 'kotlin-kapt'

android {
    ...
    buildTypes {
        ...
    }
    dataBinding {
        enabled = true
    }
}

Note that applying the kotlin-kapt plug-in allows data binding to perform annotation processing on Kotlin. You will see why that is important later in this chapter.

To use data binding in a layout file, you have to make the file a data binding layout file. You do that by wrapping the entire XML file in a <layout> tag. Make that change to activity_main.xml, as shown in Listing 19.3.

Listing 19.3  Wrapping it up (res/layout/activity_main.xml)

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <androidx.recyclerview.widget.RecyclerView
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
</layout>

The <layout> tag is your signal to the data binding library that it should work on your layout file. For layouts with this tag, the library will generate a binding class for you. By default, this class is named after your layout file, but instead of using snake_case, it is switched to the CamelCase class naming style and suffixed with Binding.

So the data binding library should have already generated a binding class for your activity_main.xml file called ActivityMainBinding. This class is what you will use for data binding: Instead of inflating a view hierarchy with setContentView(Int), you will inflate an instance of ActivityMainBinding. ActivityMainBinding will hold on to the view hierarchy for you in a property called root. In addition to that, the binding holds on to named references for each view you tagged with an android:id in your layout file.

So your ActivityMainBinding class has two references: root, which refers to the entire layout, and recyclerView, which refers to just your RecyclerView (Figure 19.2).

Figure 19.2  Your binding class

Your binding class

Your layout only has one view, of course, so both references point at the same view: your RecyclerView.

Now to use your binding class. Update onCreate(Bundle?) in MainActivity and use DataBindingUtil to inflate an instance of ActivityMainBinding (Listing 19.4).

You will need to import ActivityMainBinding like any other class. If Android Studio cannot find ActivityMainBinding, this means it was not autogenerated for some reason. Force Android Studio to generate the class by selecting BuildRebuild Project. If the class is not generated after forcing the project to rebuild, restart Android Studio.

Listing 19.4  Inflating a binding class (MainActivity.kt)

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val binding: ActivityMainBinding =
            DataBindingUtil.setContentView(this, R.layout.activity_main)
    }
}

With your binding class created, you can now access your RecyclerView and configure it.

Listing 19.5  Configuring RecyclerView (MainActivity.kt)

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding: ActivityMainBinding =
            DataBindingUtil.setContentView(this, R.layout.activity_main)

        binding.recyclerView.apply {
            layoutManager = GridLayoutManager(context, 3)
        }
    }
}

Next, create the layout file for the buttons, res/layout/list_item_sound.xml. You will be using data binding here as well, so surround your layout with a <layout> tag.

Listing 19.6  Creating the sound layout (res/layout/list_item_sound.xml)

<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
    <Button
        android:layout_width="match_parent"
        android:layout_height="120dp"
        tools:text="Sound name"/>
</layout>

Next, create a SoundHolder wired up to list_item_sound.xml.

Listing 19.7  Creating SoundHolder (MainActivity.kt)

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
    }

    private inner class SoundHolder(private val binding: ListItemSoundBinding) :
            RecyclerView.ViewHolder(binding.root) {
    }
}

Your SoundHolder expects the binding class you just implicitly created: ListItemSoundBinding.

And now create an Adapter hooked up to SoundHolder.

Listing 19.8  Creating SoundAdapter (MainActivity.kt)

class MainActivity : AppCompatActivity() {
    ...
    private inner class SoundHolder(private val binding: ListItemSoundBinding) :
            RecyclerView.ViewHolder(binding.root) {
    }

    private inner class SoundAdapter() :
        RecyclerView.Adapter<SoundHolder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
                SoundHolder {
            val binding = DataBindingUtil.inflate<ListItemSoundBinding>(
                layoutInflater,
                R.layout.list_item_sound,
                parent,
                false
            )
            return SoundHolder(binding)
        }

        override fun onBindViewHolder(holder: SoundHolder, position: Int) {
        }

        override fun getItemCount() = 0
    }
}

Finally, wire up SoundAdapter in onCreate(Bundle?).

Listing 19.9  Wiring up SoundAdapter (MainActivity.kt)

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val binding: ActivityMainBinding =
        DataBindingUtil.setContentView(this, R.layout.activity_main)

    binding.recyclerView.apply {
        layoutManager = GridLayoutManager(context, 3)
        adapter = SoundAdapter()
    }
}

You have now used data binding to set up the recycler view. Unfortunately, it does not have anything to show yet. It is time to fix that by giving it some sound files to display.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.148.124