경험의 기록

코틀린에서는 자바와 달리 findViewById를 쓰지 않고 ID를 직접 사용할 수 있었다.

하지만 이 기능을 포함한 Extension이 21년 9월 즈음에 완전히 폐기될 예정이다.

 

android-developers.googleblog.com/2020/11/the-future-of-kotlin-android-extensions.html

 

The future of Kotlin Android Extensions

Posted by David Winer, Product Manager The Android Kotlin Extensions Gradle plugin (not to be confused with Android KTX ) was release...

android-developers.googleblog.com

폐기되는 이유와, 대체 방법은 이 글에서 읽을 수 있다.

구글에서는 대체방법으로 뷰바인딩을 제시하고 있다.

 

ViewBinding 장점

  • Null 안전 : Viewbinding은 뷰의 직접 참조를 생성하므로 null 예외가 발생할 위험이 없다.
  • Type 안전 : 각 바인딩 클래스에 있는 필드의 유형이 xml 파일에서 참조하는 뷰와 일치한다.

 

사용해보기

buildFeatures {
        viewBinding true
    }

bulid.gradle (Module)android에 추가해준다.

viewBinding을 사용 설정하게 되면,

각 XML 파일 마다 바인딩 클래스가 자동으로 생성된다.

 

예를 들어 레이아웃 이름이

activity_main 인 경우

ActivityMainBinding 이라는 이름으로 자동 생성된다.

 

viewBinding은 액티비티프래그먼트에서의 사용법이 다르다.

 

액티비티에서

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="307dp"
        android:text="TextView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="17dp"
        android:text="TextView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>

테스트할 임의의 xml을 만들어주고

 

package org.techtown.viewbinding

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import org.techtown.viewbinding.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    // lateinit 사용
    private lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // binding class 인스턴스 생성
        binding = ActivityMainBinding.inflate(layoutInflater)
        // binding class의 root를 참조하여 view로
        val view = binding.root
        setContentView(view)

        // 접근 가능
        binding.textView.text = "변경!"
    }

}

ActivityMainBinding 타입의 변수를 lateinit로 선언해주고

onCreate 호출시 binding class의 인스턴스를 생성하여 할당해줌으로써

view 내부의 텍스트뷰에 접근이 가능해졌다.

 

 

프래그먼트에서

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#A64242"
    tools:context=".TestFragment">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="테스트 프래그먼트 입니다!"
        android:gravity="center"
        android:textSize="24sp" />

</FrameLayout>

 

테스트할 임의의 fragment를 만들고 메인 액티비티에 넣어주었다.

 

package org.techtown.viewbinding

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import org.techtown.viewbinding.databinding.FragmentTestBinding

class TestFragment : Fragment() {

    // 메모리 관리를 위함
    private var _binding : FragmentTestBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        // View Binding
        _binding = FragmentTestBinding.inflate(inflater,container,false)

        // root를 참조
        return binding.root
    }

    // 프래그먼트는 뷰보다 오래 지속 . 프래그먼트의 onDestroyView() 메서드에서 결합 클래스 인스턴스 참조를 정리
    override fun onDestroyView() {
        _binding = null
        super.onDestroyView()
    }
}

액티비티에서 했던 방법과 유사하게 진행한다.

프래그먼트는 뷰보다 오래 지속되므로 프래그먼트가 destroy 될때 인스턴스 참조를 정리해줌으로써 메모리 관리를 더 효율적으로 할수 있다.

 

 

class MainFragment : Fragment(R.layout.fragment_main) {

    // 뷰모델 생성
    private val viewModel by viewModels<WeatherViewModel>()

    // 참조 관리
    private var _binding : FragmentMainBinding? = null
    private val binding get() = _binding

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // 뷰바인딩
        _binding = FragmentMainBinding.bind(view)
    }

    // 프래그먼트는 뷰보다 오래 지속 . 프래그먼트의 onDestroyView() 메서드에서 결합 클래스 인스턴스 참조를 정리
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

또한 다른 방법으로

onViewcreated에서 bind로 view를 받아와 사용할 수도 있다.

 

github.com/HanYeop/AndroidStudio-Practice/tree/master/ViewBinding

 

HanYeop/AndroidStudio-Practice

AndroidStudio Practice. Contribute to HanYeop/AndroidStudio-Practice development by creating an account on GitHub.

github.com

 

 

 

참조 :

developer.android.com/topic/libraries/view-binding

choheeis.github.io/newblog//articles/2020-09/viewBinding

 

 

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading