Data Binding - YamamotoDesu/Yamamoto-Notes GitHub Wiki

1. How to set up

app/build.gradle

android {
    ใƒปใƒปใƒป
    dataBinding {
        enabled = true
    }
ใ€€ใ€€ใ€€ใ€€ใ€€ใ€€ใƒปใƒปใƒป
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/sample_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World" />
    </LinearLayout>

</layout>

MainActivity.kt

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.codewithkyo.databinding.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)
//        val sampleTextView: TextView = findViewById(R.id.sample_text_view)
//        sampleTextView.text = "Hello World"

        val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.sampleTextView.text = "Hello World"
    }
}

2. Set Button

activity_main.xml

        <Button
            android:id="@+id/sample_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Binding!" />

MainActivity.kt

        val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.sampleTextView.text = "Hello World"

        binding.sampleButton.setOnClickListener {
            binding.sampleTextView.text = "Hello, Binding!"
        }

Tips

You do not need to use "findViewById" as using "Kotlin Android Extension"

apply plugin: 'kotlin-android-extentions'

3. data tag

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="counter"
            type="int" />

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/sample_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{`Count:` + counter}" />

        <Button
            android:id="@+id/sample_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Binding!" />

    </LinearLayout>

</layout>

MainActivity.kt

        val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.sampleTextView.text = "Hello World"
        binding.counter = 1

        binding.sampleButton.setOnClickListener {
            binding.counter += 1
        }

4. Pass data from view(2 Ways Binding)

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="inputText"
            type="String" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:text="@={inputText}" />

        <Button
            android:id="@+id/button_confirm"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Confirm" />

    </LinearLayout>

</layout>

MainActivity.kt

class MainActivity : AppCompatActivity() {

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

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

        binding.buttonConfirm.setOnClickListener {
            Toast.makeText(this, binding.inputText, Toast.LENGTH_LONG).show()
        }
    }
}

5.Hide by data binding

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <import type="android.view.View" />

        <variable
            name="enableAlarm"
            type="boolean" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <Switch
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:checked="@={enableAlarm}"
            android:padding="16dp"
            android:text="ใ‚ขใƒฉใƒผใƒ " />

        <TimePicker
            android:id="@+id/time_picker"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="@{enableAlarm ? View.VISIBLE : View.GONE}"
            />

    </LinearLayout>

</layout>

Tips you can call a function from view

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="com.codewithkyo.databinding.Converter"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text='@{Converter.INSTANCE.echo("Hello")}' />

    </LinearLayout>

</layout>

Object

object Converter {
    fun echo(value: String): String {
        return "$value $value"
    }
} 

Tips Event Data Binding

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="text"
            type="String" />

        <variable
            name="onClick"
            type="android.view.View.OnClickListener" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{text}' />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{onClick}"
            android:text="PUSH" />

    </LinearLayout>

</layout>

MainActivity

class MainActivity : AppCompatActivity() {

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

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

        binding.setOnClick {
            binding.text = "Click!"
        }
    }
}

Tips ListView Data Binding

list_example.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="item"
            type="com.codewithkyo.databinding.ListItem" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text='@{item.text}'
            android:layout_weight="1"
            android:textStyle="bold" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{item.due.toString()}" />

    </LinearLayout>

</layout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" />

</layout>

ListItem.kt

data class ListItem(val text: String, val due: Date)

MainActivity.kt

class MainActivity : AppCompatActivity() {

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

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

        val adapter = MainListAdapter(this).apply {
            add(ListItem("ใ‚ดใƒŸๅ‡บใ—", Date()))
            add(ListItem("ๅ‹‰ๅผทใ™ใ‚‹", Date()))
            add(ListItem("ๅฏใ‚‹", Date()))
        }
        binding.listView.adapter = adapter
    }
}

class MainListAdapter(context: Context): ArrayAdapter<ListItem>(context, 0) {
    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        val binding: ListExampleBinding
        if (convertView == null) {
            binding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.list_example, parent, false)
            binding.root.tag = binding
        } else {
            binding = convertView.tag as ListExampleBinding
        }

        binding.item = getItem(position)
        return binding.root
    }
}

Tips Using Fragment with Data Binding

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <FrameLayout
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" >

        <fragment
            android:id="@+id/fragment_main"
            android:name="com.codewithkyo.databinding.MainFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </FrameLayout>

</layout>

fragment_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas:android.com/tools">
    
    <data>
        
        <variable
            name="kinoko"
            type="int" />
        
        <variable
            name="takenoko"
            type="int" />
        
    </data>

    <GridLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:columnCount="2"
        tools:context=".MainFragment" >

        <TextView
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:gravity="center"
            android:text="@{Integer.toString(kinoko)}"
            android:textSize="42sp" />

        <TextView
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:gravity="center"
            android:text="@{Integer.toString(takenoko)}"
            android:textSize="42sp"
            />

        <Button
            android:id="@+id/button_kinoko"
            android:layout_columnWeight="1"
            android:text="ใใฎใ“" />

        <Button
            android:id="@+id/button_takenoko"
            android:layout_columnWeight="1"
            android:text="ใŸใ‘ใฎใ“" />

    </GridLayout>

</layout>

MainActivity.kt

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.codewithkyo.databinding.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

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

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

    }
}

MainFragment.kt

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import com.codewithkyo.databinding.databinding.FragmentMainBinding

class MainFragment : Fragment() {
    private lateinit var binding: FragmentMainBinding

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_main, container, false)
        return binding.root
    }

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

        binding.buttonKinoko.setOnClickListener {
            binding.kinoko += 1
        }

        binding.buttonTakenoko.setOnClickListener {
            binding.takenoko += 1
        }
    }
}

6. RecyclerView with Data Binding

list_example.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="item"
            type="com.codewithkyo.databinding.ListItem" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text='@{item.text}'
            android:layout_weight="1"
            android:textStyle="bold" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{item.due.toString()}" />

    </LinearLayout>

</layout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" />

</layout>

MainActivity.kt

class MainActivity : AppCompatActivity() {

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

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

        val adapter = ExampleAdapter(this)
        adapter.items = listOf(
            ListItem("ใ‚ดใƒŸๅ‡บใ—", Date()),
            ListItem("ๅฏใ‚‹", Date()),
            ListItem("ใŠๅ‡บใ‹ใ‘", Date())
        )

        binding.recyclerView.layoutManager = LinearLayoutManager(this)
        binding.recyclerView.adapter = adapter
    }

    class ExampleAdapter(context: Context) : RecyclerView.Adapter<ExampleAdapter.Holder>() {
        var items: List<ListItem> = emptyList()
        private val inflater = LayoutInflater.from(context)

        override fun getItemCount(): Int = items.size

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
            val binding: ListExampleBinding = DataBindingUtil.inflate(inflater, R.layout.list_example, parent, false)

            return Holder(binding)
        }

        override fun onBindViewHolder(holder: Holder, position: Int) {
            holder.binding.item = items[position]
            holder.binding.executePendingBindings()
        }

        class Holder(val binding: ListExampleBinding) : RecyclerView.ViewHolder(binding.root)
    }
}

Tips How to pass Data bing to other instance or thread safe processing

val inflater = LayoutInflater.from(context)
val binding = ViewExampleBinding = DataBindingUtil.inflate(inflater, R.layout.list_repository, parent, false)
val v: View = binding.root
// Reaccess to the object again
val reBind: ViewExampleBinding = DataBindingUtil.bind(v)
โš ๏ธ **GitHub.com Fallback** โš ๏ธ