본문 바로가기
Android/Data Binding

[데이터 바인딩] Fragment에서 DataBinding 사용하기

by SungJe 2021. 7. 9.

시작하기

본 글에서는 Fragment에서 데이터 바인딩을 사용하는 방법에 대해서 알어보도록 한다.

데이터 바인딩의 기본 사용 방법은 이전글을 참고한다.

[DataBinding] 데이터 바인딩 사용하기

Fragment 생성

안드로이드 스튜디오에서 빈 플레그먼트를 생성하면 자동으로 코드가 생성된다. 바인딩 객체는 UI를 초기화하는 시점인 onCreateView 콜백 함수에서 초기화할 수 있다.

  • 기존 소스코드
override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_blank, container, false)
}
  • 데이터 바인딩 소스코드
override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    val binding: FragmentCounterBinding = 
    	DataBindingUtil.inflate(inflater, R.layout.fragment_counter, container, false)
    val view = binding.root

    return view
}

Full Source

build.gradle (:app)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "com.sungje365.fragmenttest"
        minSdkVersion 23
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures {
        dataBinding true
    }
}

dependencies {
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    def lifecycle_version = "2.3.1"
    def fragment_version = "1.3.5"

    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    // Lifecycle
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
    // Annotation processor
    kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
    // Fragment
    implementation "androidx.fragment:fragment-ktx:$fragment_version"

    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.6.0'
    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.view.MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/frag_main"
        android:name="com.sungje365.fragmenttest.ui.view.CounterFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
fragment_counter.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"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="viewModel"
            type="com.sungje365.fragmenttest.ui.viewmodel.CounterViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ui.view.CounterFragment">

        <TextView
            android:id="@+id/tv_frag_count"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{Integer.toString(viewModel.counter)}"
            android:textSize="100sp"
            android:textStyle="bold"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintTop_toBottomOf="@id/tv_frag_count"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent">

            <Button
                android:id="@+id/btn_frag_add"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="8dp"
                android:text="@string/all_add"
                android:onClick="@{() -> viewModel.increase()}" />

            <Button
                android:id="@+id/btn_frag_sub"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="8dp"
                android:text="@string/all_sub"
                android:onClick="@{() -> viewModel.decrease()}" />
        </LinearLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
MainActivity.kt
package com.sungje365.fragmenttest.ui.view

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.sungje365.fragmenttest.R

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}
CounterFragment.kt
package com.sungje365.fragmenttest.ui.view

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 androidx.fragment.app.activityViewModels
import com.sungje365.fragmenttest.R
import com.sungje365.fragmenttest.databinding.FragmentCounterBinding
import com.sungje365.fragmenttest.ui.viewmodel.CounterViewModel

class CounterFragment : Fragment() {
    private lateinit var binding: FragmentCounterBinding
    private val model: CounterViewModel by activityViewModels()

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

        binding.apply {
            viewModel = model
            lifecycleOwner = this@CounterFragment
        }

        return binding.root
    }
}
CounterViewModel.kt
package com.sungje365.fragmenttest.ui.viewmodel

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch

class CounterViewModel : ViewModel() {
    val counter: MutableLiveData<Int> by lazy { MutableLiveData<Int>() }

    init {
        viewModelScope.launch {
            counter.value = 0
        }
    }

    fun increase() {
        counter.value = counter.value?.plus(1)
    }

    fun decrease() {
        counter.value = counter.value?.minus(1)
    }
}

'Android > Data Binding' 카테고리의 다른 글

[데이터 바인딩] DataBinding 사용하기  (0) 2021.07.02