뷰 바인딩

상환·2021년 8월 26일
0

안드로이드 공부

목록 보기
1/7
post-thumbnail

소개말

안드로이드 프로젝트를 처음 생성해서 뷰에 데이터를 표현할 때 가장 많이 쓰는 함수는 "View.findViewById(id: Int)" 일 것입니다. 하지만 뷰에 쓰는 컴포넌트가 많아질 수록 반복해서 호출해야하고, 코드가 길어지는 문제를 야기합니다. 우리는 바인딩을 통해 이러한 문제를 해결해보려 합니다.

코틀린에선 findViewById를 쓰지않고 컴포넌트의 id를 통해 바로 접근할 수 있었지만 androidStudio 4.1에서 kotlin-android-extensions 플러그인이 다양한 문제로 인해 기본적으로 제공되지 않으면서 id를 통해 접근할 수 없게되었다.

1. 바인딩의 종류

바인딩에는 2가지 방법이 있습니다. 간단하게 뷰를 가져오기만 하는 뷰 바인딩, 바인딩 오브젝트를 통한 양방향 접근이 가능한 데이터바인딩이 있습니다. 그 중 살펴볼 내용은 뷰 바인딩입니다.

2. 뷰 바인딩

정의

뷰 바인딩은 findViewById를 대체할 수 있는 방법 중 하나로 바인딩 클래스를 통해 레이아웃 Id로 모든 뷰의 직접참조가 가능합니다.

사용법

1. build.gradle 의존성 주입

android {
    ...
    viewBinding {
    	enabled = true
    }
}

// Android Studio 4.0 
android { 
    buildFeatures { 
    	viewBinding = true 
    } 
}

안드로이드 스튜디오 4.0부터는 viewBinding의 위치가 buildFeatures로 이동되서 아래와 같이 사용하면 됩니다.

만약 바인딩 클래스를 생성하는 동안 특정 컴포넌트는 바인딩에서 제외하고 싶다면 tools:viewBindingIgnore="true"를 넣어줍니다.

<LinearLayout
            ...
            tools:viewBindingIgnore="true" >
        ...
</LinearLayout>

2. Activity에서 호출

모듈에 뷰 바인딩을 사용하도록 설정하면 모듈의 각 XML에 대해 바인딩클래스가 생기게 됩니다. 바인딩 클래스의 이름은 XML 이름을 카멜 케이스로 변환한 뒤 'Binding'를 추가적으로 붙여주게됩니다.

Activity에서 바인딩 클래스 인스턴스를 설정하려면 onCreate()에서 다음과 같은 절차를 따라야 합니다.

  1. 생성된 바인딩 클래스에 포함된 정적 inflate() 메서드를 호출합니다. 그러면 활동에서 사용할 바인딩 클래스 인스턴스가 생성됩니다.
  2. getRoot() 메서드를 호출하거나 Kotlin 속성 구문을 사용하여 루트 뷰 참조를 가져옵니다.
  3. 루트 뷰를 setContentView()에 전달하여 화면상의 활성 뷰로 만듭니다.
//lateinit으로 스코프를 열어줌
    private lateinit var binding: ResultProfileBinding

    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        binding = ResultProfileBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
    }

3. Fragment에서 호출

Fragment에서 호출시 1, 2단계는 같지만 3단계에선 setContentView()에 루트뷰를 전달 하는 것이 아닌 onCreateView()에서 루트뷰를 반환해주는 차이를 보입니다.

    private var binding: ResultProfileBinding? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = ResultProfileBinding.inflate(inflater, container, false)
        val view = binding.root
        return view
    }

    override fun onDestroyView() {
        super.onDestroyView()
        binding = null
    }

4. 사용

사용법은 코드단에서 findViewById를 썼던 것 처럼 id를 통해 호출하면 됩니다.

    binding.name.text = viewModel.name
    binding.button.setOnClickListener { viewModel.userClicked() }

장점

  1. 코드의 길이를 줄일 수 있다.
  2. Null Safe : id를 통해 직접참조하므로 유효하지 않은 id로 인한 nullPointerException이 발생하지않는다.
  3. Type Safe : 각 바인딩 클래스에 있는 필드의 유형이 XML 파일에서 참조하는 뷰와 일치한다. 즉, 클래스 변환 예외가 발생할 위험이 없다.

마치며

코드를 획기적으로 줄일 수 있고 모듈의 안전을 보장할 수 있는 뷰 바인딩을 살펴봤습니다. 다음엔 양방향 접근이 가능한 데이터바인딩을 살펴보겠습니다.
profile
레모네이드 커피

0개의 댓글