안녕하세요.
이번 포스팅에서는 안드로이드에서 뷰의 성능 개선을 위한
3가지 태그를 설명 드리려고 합니다.
우리가 일반적으로 xml에 레이아웃을 정의하면
똑같은 뷰를 여러번 정의하거나 쓸까 말까한 뷰도 생성되게 정의하거나
또는 레이아웃의 깊이가 깊어져 성능이 안좋아 지는 경우가 있습니다.
이를 개선하기 위해 사용되는 것이 위 3개의 태그입니다.
첫째로 같은 레이아웃을 여러번 그릴 때 <include> 태그로 이를 개선할 수 있습니다.
<include> 를 사용하면 하나의 레이아웃을 정의함으로써 동일한 레이아웃을 여러번
정의할 수 있기 때문에 굉장히 편리한 태그입니다.
우선 include할 layout 파일을 만든 후 이를 <include>으로 감싼다음
android:layout = "@layout/include_appbar" 를 정의하여 사용할 수 있습니다.
또한 데이터바인딩을 이용하여 includ_appbar의 변수에 접근할 수 있습니다.
<include layout="@layout/include_appbar"
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
두번째로 뷰의 깊이를 줄이기 위해 사용되는 <merge> 태그입니다.
만약 뷰를 배치하는데 불필요하게 레이아웃이 중첩되면(리니어 안에 또 다른 리니어) 뷰를 그리는데
성능만 떨어지게 됩니다.
이 때 <merge>태그를 사용하면 중복되는 레이아웃 없이 그릴 수 있게 됩니다.
<merge xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@color/purple_200" />
<TextView
android:id="@+id/body"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@color/purple_200"/>
</merge>
이렇게 <merge> 태그로 감싼 후
<include layout="@layout/merge_text"/>
<include>로 감싸 호출하시면 됩니다.
다만 주의해야할 점은 ConstraintLayout에서 사용할 때 <include>태그안의 Constraint조건들이 무시되기 때문에
적절한 상황에서 사용하시면 될거 같습니다.
또한 <merge> 태그 안에 아이디를 통한 바인딩이 안되기 때문에 이 또한 주의하셔야 할거 같습니다.
(예를 들면 binding.merge_text.aaa 가 안됨)
세번째로 뷰를 쓰일지 안쓰일지 모르는 상황일 때 필요한 상황에서 inflate()하기 위한 <viewstub> 태그가 있습니다.
뷰를 필요한 시점에 로드하기 때문에 안쓰이는 상황에서 효율적으로 활용할 수 있습니다.
일단 아래 처럼 새로운 레이아웃을 생성해 줍니다.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="50dp"
android:layout_height="50dp">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
그리고 쓰이는 곳에서 <viewstub>코드로 감싸 사용하시면 됩니다.
<ViewStub
android:id="@+id/progressViewStub"
android:layout="@layout/viewstub_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
그리고 클래스 파일에서
val progressViewStub = binding.progressViewStub
if(!progressViewStub.isInflated){
val view: View? = progressViewStub.viewStub?.inflate()
}
이렇게 인플레이션 해주면 된다.
viewStub에서 데이터바인딩을 할 때 불편한점이 있다.
viewStub이 inflate() 호출 후 그에 대한 바인딩을 수행하는 리스너를 달아야 한다는 점이 있다.
var stubBinding: ViewstubProgressBinding? = null
progressViewStub.setOnInflateListener { stub, inflated ->
stubBinding = ViewstubProgressBinding.bind(inflated)
}
위 코드들은 아래 깃허브에서 확인하실 수 있습니다.
https://github.com/ckdrb7017/BlogProject/tree/master/ViewReusing
https://developer.android.com/training/improving-layouts/loading-ondemand?hl=ko
'개발 > 안드로이드' 카테고리의 다른 글
안드로이드 Annotation을 이용한 코드 생성(2) (0) | 2021.08.08 |
---|---|
안드로이드 Annotation을 이용한 코드 생성(1) (0) | 2021.08.02 |
안드로이드 뷰가 그려지는 과정 (0) | 2021.06.09 |
안드로이드 LiveData setValue 와 postValue (0) | 2021.05.13 |
안드로이드 구글STT에서 Recording이 안되는 이유 (9) | 2021.04.26 |
댓글