ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • View Binding 사용해보기
    Android/Android 2020. 11. 5. 17:38

     

    Kotlin 1.4.20 버전에서 Kotlin Android Extensions Compiler 플러그인이 Deprecated 됬다

    왜 Kotlin Android Extensions Compiler 플러그인을 Deprecated 했을까?

    1. 글로벌 네임스페이스로 노출이 되어 현재 Activity 에서 사용중이지 않은 View 를 참조 할 수 있다.
      이에 Null Safty 하지 않다.
    2. 오직 Kotlin 언어로만 접근 및 사용이 가능하다.

    그러면 무엇으로 대체를 해야 할까?

    • View Binding
      • View Binding 은 Binding 뿐만 아니라 View Lookup 에도 권장되지만 Android Kotlin Extensions와 비교할 때 오버헤드가 약간 추가된다.
      • Kotlin Extensions 와 비교했을 때, View Lookup 과 타입 안전성의 컴파일 시간 체크가 추가되었다.
    • findViewById
      • 예전부터 계속 해오던 방식

    findViewById를 계속 쓰기에는 매우 unpretty 하다. 그래서 ViewBinding 을 한번 써보도록 하겠다.


    목차


    1. 뷰 바인딩은 무엇인가?
    2. 뷰 바인딩 준비하기
    3. 액티비티에서 뷰 바인딩 사용하기
    4. 프래그먼트에서 뷰 바인딩 사용하기
    5. Include 태그에서 뷰 바인딩 사용하기

    뷰 바인딩은 무엇인가?


    • 뷰 바인딩은 View 와 상호 작용하는 코드를 보다 쉽게 작성할 수 있는 기능이다.
    • 모듈에서 뷰 바인딩을 활성화하면 해당 모듈에 있는 각 XML 레이아웃 파일에 대한 바인딩 클래스를 생성한다.
    • 바인딩 클래스의 인스턴스는 해당 레이아웃에 ID가 있는 모든 뷰에 대한 직접 참조를 포함한다.
    • 뷰 바인딩은 뷰가 XML 있는지 탐지하고 @Nullable 속성을 생성하기에 Null-safe 하다.
    • View Binding은 Java 및 Kotlin과 함께 작동한다.

    무엇보다 가장 큰 장점은 NullSafty 하다는 소리인데 예를 들어 이런 경우를 생각해 보도록 하자.

    ex ) RegisterActivity, LoginActivity 에 edit_password 라는 뷰를 둘다 가지고 있을 때, 둘중 하나의 액티비티에서 참조를 하려면 아래와 같이 뜰 것이다.

    물론 잘못쓰면 다시 고치면 되지만 매번 실수를 할 수 있는거고 이러한 문제는 런타임에서 나타난다는 것이다.

    이러한 문제점은 버그를 수정해서 기쁘다는 표정으로 빌드를 하고 테스트하다가 죽는 상황이 발생한다. ( 히히... )

    뷰 바인딩 준비하기


    그러면 뷰바인딩을 한번 사용해 보도록 하자

    우선 build gralde 파일에 아래와 같이 추가해주도록 하자 그러면 이제 끝이다.

    android {
            buildFeatures {
            viewBinding true
          }
    }

    만약에 Binding 클래스를 생성하기 싫은 레이아웃은 아래와 같이 viewBindingIgnore 를 true 해주면 된다.

    <LinearLayout 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"
        tools:viewBindingIgnore="true"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
    <LinearLayout>

    추가적으로 테스트를 하기 위해 아래와 같이 코드를 구성하였다.

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout ... >
    
        <TextView ... />
    
        <ImageView ... />
    
        <Button ... />
    
    </LinearLayout>

    액티비티에서 뷰 바인딩 사용하기


    뷰 바인딩을 활성화 하기위해서는 onCreate() 에서 아래의 2가지를 진행 해주면 된다.

    1. 생성된 바인딩 클래스에 포함되어있는 정적 함수인 inflate 를 호출해줘서 생성된 바인딩 클래스를 해당 액티비티에서 사용하도록 한다.
    2. setContentView에 위에서 생성한 binding 객체로 부터 getRoot() 나 코틀린 문법을 통해 root 객체를 얻어 넣어주면 된다.
    class MainActivity : AppCompatActivity() {
    
        private lateinit var binding : ActivityMainBinding
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            binding = ActivityMainBinding.inflate(layoutInflater)
            setContentView(binding.root)
        }
    
    }

    binding 변수에 접근을 하면 아래와 같이 아까 레이아웃에서 설정한 3개의 뷰 컴포넌트들이 보인다.

    무려 Nullable 하다! 즉, 안전하다는 소리다.

    사용은 엄청 간단하다. 그냥 평소에 하던대로 사용을 하면 된다.

    binding.button.setOnClickListener {
        binding.textView.text = "Hello?"
        binding.imageView.setImageDrawable(
            resources.getDrawable(
                R.drawable.ic_launcher_foreground,
                null
            )
        )
    }

    프래그먼트에서 뷰 바인딩 사용하기


    프래그먼트를 하나 생성하고 바로 바인딩 객체를 생성해 주도록 하자

    private lateinit var binding: FragmentSubMainBinding
    
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentSubMainBinding.inflate(layoutInflater, container, false)
        return binding.root
    }

    바인딩 객체를 생성하는 거 자체는 액티비티와 다를 것이 없다.

    굳이 뽑자면 프래그먼트는 onCreateView에서 뷰 객체를 생성하는 것이다.

    override fun onStart() {
      super.onStart()
      binding.button1.setOnClickListener {
          Toast.makeText(this@SubMainFragment.context, binding.button1.text, Toast.LENGTH_SHORT)
              .show()
      }
        // ...
    }

    onStart 에서 바인딩 객체를 통해 리스너 및 부가적인 작업을 해주면된다.

    Include 태그에서 뷰 바인딩 사용하기


    Include 태그로 삽입 된 뷰의 경우는 더욱이 쉽게 바인딩이 가능하다.

    우선 아래의 코드를 프래그먼트나 액티비티에 삽입해준다.

    <include
        android:id="@+id/layout_include"
        android:layout_width="600dp"
        android:layout_height="600dp"
        layout="@layout/include_layout"/>

    필자는 프래그먼트 객체에 넣어보았고 프래그먼트 클래스로 가서 아래와 같이 변수 선언 및 초기화를 해주면 된다.

    private lateinit var binding: FragmentSubMainBinding
    private lateinit var includeBinding: IncludeLayoutBinding
    
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentSubMainBinding.inflate(layoutInflater, container, false)
        includeBinding = binding.layoutInclude
        return binding.root
    }

    끝.

    마무리


    간단하게 ViewBinding을 사용해 보았다 이렇게 간단하게 사용이 가능하고 Android Kotlin Extension 을 사용 하면서 nullable 하게 접근하지 않아도 되고 findViewByID를 사용하지 않아도 된다.

    다들 뷰 바인딩 하자.

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

    테스트코드를 왜 작성 해야 하는 걸까?  (0) 2020.08.21

    댓글

Designed by Tistory.