Android

findviewById 성능문제와 대체법 (binding)

Dean83 2022. 5. 23. 16:50

1. findviewById 문제점

    - UI 속성이 많거나 계층구조로 되어 있을 경우, 탐색하는데 시간이 오래 걸린다. (퍼포먼스 문제)
    - 사용 할때마다 매번 탐색한다

 

2. 해결법 

     - binding 을 이용하여 최초 1회 탐색을 하고(앱 실행시) 그 이후부턴 탐색하지 않는다
        * findviewById 로 한번 탐색한걸 맴버변수에 넣으면 결국 똑같은거 아닌가...?

 

3. binding 설명

    - UI 뿐 아니라, 데이터 연동 또한 바인딩이 가능하다. 즉 string.xml 이 아닌 클래스 형식의 데이터를

       UI에 바인딩 할 수 있다. 

 

4. binding 사용을 위한 세팅

     - build.gradle (app) 을 연다 -> android {} 안에 buildFeatures { dataBinding true } 를 추가하고 싱크한다.
       

    buildFeatures{
        dataBinding true
    }


     - binding을 이용할 레이아웃을 연다 -> xml 에디팅을 통해 최상위 항목이 layout tag가 되도록 수정한다. 

<?xml version="1.0" encoding="utf-8"?>
<layout 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:context=".MainActivity">
    
    .....
    
</layout>

5. binding 할 클래스 생성

    - 프로젝트에서 마우스 우클릭 -> 클래스 추가 하여 바인딩에 사용할 클래스를 추가한다. 

    - class 는 data class 이름 (변수 세팅) 으로 설정한다

    - class의 이름 첫문자는 반드시 대문자로 적는다 (안그러면 빌드시 오류 발생함) 

//클래스명 첫문자는 반드시 대문자로.
data class 클래스명 (var 변수명: 변수타입, var 변수명: 변수타입)

 

6. xml에서 클래스 연결

    - layout 태그 바로 밑에 data 태그를 추가한다. (즉, layout 태그와 하위 view 태그 사이에 추가)

    - variable 태그를 추가하여 5. 에서 추가한 클래스를 바인딩 한다.

<layout 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:context=".MainActivity">
    <data>
        <variable
            name="원하는 변수명"
            type="위에서 생성한 클래스의 전체 경로 (com......클래스명)" />
    </data>
    
    ....
    
</layout>

    - 원하는 UI 뷰에서 변수명.맴버변수명을 연결한다. (textview 예)

<TextView
    android:id="@+id/textView"
    style="@style/TextStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textAlignment="center"
    android:text="@={위에서 설정한 클래스의 변수명.클래스의 맴버변수명}"
 />

7. 코드에서 binding 설정 및 사용

    - 맴버변수로, binding을 추가한다 

private lateinit var binding : ActivityMainBinding

    - 맴버변수로 데이터 클래스 변수를 생성한다

private var 변수명 : 데이터클래스명 = 데이터클래스명(인자값)

    - binding 맴버변수에 데이터클래스 맴버변수를 연결한다.

       layout의 xml 에서 variable 의 name어트리뷰터에 적은 이름과 data클래스의 변수명을 연결한다. 

       (예를들어 xml의 variable 태그에 지정한 name이 test이고 데이터클래스 맴버변수명이 testvar이라면)

    - setContentView(R.layout.레이아웃명) 을 지우고, DataBindingUtil.setContentView를 이용한다.

override fun onCreate(....)
{
  ...
  binding = DataBindingUtil.setContentView(this,R.layout.activity_main)
  binding.test = testvar
  ...
}

 

8. findviewById 대신 사용

    - binding.id 이름 으로 접근하여 사용한다. (binding 맴버변수명이 binding일 경우)   

binding.button.setOnClickListner {....}

 

9. binding 변수의 데이터 변경시 적용법

    - xml의 variable로 설정한 데이터를 코드에서 변경시, = 로만 값을 배정해선 안되고, apply 함수 및 invalidate를 호출해야 한다. 
    - 변수명? 는 xml의 variable의 name 어트리뷰트에서 설정한 이름이며, 맴버변수명은 data클래스의 맴버변수명 이다.

 binding.apply {
            변수명?.맴버변수명 = ""
            invalidateAll()
        }