티스토리 뷰
이번 포스팅에서는 Fragment 에서 View Binding 사용법에 대해서 자세히 알아보자.
참고로, 지난 포스팅에서는 View Binding 의 개요, View 접근을 위한 다른 방식들과 비교, 사용법에 대해 알아 보았다.
Fragment Lifecycle
Fragment 는 하단과 같이 Fragment 의 고유한 LifeCycle 과 View 와 관련한 LifeCycle 이 존재한다.
◼ Fragment LifeCycle : onAttach() ~ onDetach()
화면에 보이지 않는 상태에서 호출
◼ Fragment View LifeCycle : onCreateView() ~ onDestroyView()
화면을 구성할 때 호출
Memory leak
Memory leak 이란 더 이상 사용하지 않는 객체가 GC 에 의해 회수되지 않고 계속 축적되는 현상이다.
(상세설명은 구글링......)
Fragment Lifecycle 에서 본 것 처럼 Fragment 의 LifeCycle 은 View 의 LifeCycle 보다 오래 유지된다.
Fragment 의 onCreateView() 에서 viewBinding 을 한 후 다른 frament 로 교체하게 된다면 viewBinding 은 이미 참조하고 있는 것이 있기 때문에 memory leak 이 발생하게 된다.
하단은 안드로이드 공식 문서에서 가이드 하고 있는 Frament 에서 ViewBinding 사용법이다.
즉, Fragment 에서 ViewBinding 사용 시 memory leak 의 위험이 있으니 onDestoryView() 에서
binding 변수를 null 로 해줘야 한다.
Solution
Fragment 에서 ViewBinding 시 memory leak 때문에 onDestory() 에서 binding 개체를 null 로 만들어야 한다.
하지만, 매번 binding 개체를 null 로 만들어야 하는 반복적인 작업이 귀찮다면 하단의 대안도 있다.
◼ onViewCreated() 에서 ViewBinding 참조 끝내기
ViewBinding 을 멤버로 만들지 않고 onViewCreated() or onCreateView() 에서 참조를 모두 끝내는 방식이다.
class MainFragment : Fragment(R.layout.fragment_main) { | |
override fun onViewCreated(a_view: View, a_savedInstanceState: Bundle?) { | |
super.onViewCreated(a_view, a_savedInstanceState) | |
val viewBinding = FragmentMainBinding.bind(a_view) | |
viewBinding.tvTitle.text = "Parkho" | |
} | |
} |
◼ BaseFragment 상속해서 사용하기
BaseFragment 를 만들어 반복되는 코드를 따로 모아 놓은 방식이다.
typealias Inflate<T> = (LayoutInflater, ViewGroup?, Boolean) -> T | |
abstract class BaseFragment<a_viewBinding : ViewBinding>(private val inflate: Inflate<a_viewBinding>) : | |
Fragment() { | |
private var _viewBinding: a_viewBinding? = null | |
val viewBinding get() = _viewBinding!! | |
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { | |
_viewBinding = inflate.invoke(inflater, container, false) | |
return viewBinding.root | |
} | |
override fun onDestroyView() { | |
super.onDestroyView() | |
_viewBinding = null | |
} | |
} |
class MainFragment : BaseFragment<FragmentMainBinding>(FragmentMainBinding::inflate) { | |
override fun onViewCreated(a_view: View, a_savedInstanceState: Bundle?) { | |
super.onViewCreated(a_view, a_savedInstanceState) | |
viewBinding.viewBinding.tvTitle.text = "Parkho" | |
} | |
} |
◼ Kotlin Delegated properties 사용하기
안드로이드 공식문서에서는 binding null 처리를 했지만, 구글 아키텍쳐 샘플 소스 코드에서는 AutoCleardValue 를 만들어 위임 패턴으로 사용한다.
구글 샘플 코드에 있는 AutoCleardValue를 사용하는 방식이다.
class AutoClearedValue<T : Any>(val fragment: Fragment) : ReadWriteProperty<Fragment, T> { | |
private var _value: T? = null | |
init { | |
fragment.lifecycle.addObserver(object: DefaultLifecycleObserver { | |
override fun onCreate(owner: LifecycleOwner) { | |
fragment.viewLifecycleOwnerLiveData.observe(fragment) { viewLifecycleOwner -> | |
viewLifecycleOwner?.lifecycle?.addObserver(object: DefaultLifecycleObserver { | |
override fun onDestroy(owner: LifecycleOwner) { | |
_value = null | |
} | |
}) | |
} | |
} | |
}) | |
} | |
override fun getValue(thisRef: Fragment, property: KProperty<*>): T { | |
return _value ?: throw IllegalStateException( | |
"should never call auto-cleared-value get when it might not be available" | |
) | |
} | |
override fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) { | |
_value = value | |
} | |
} | |
/** | |
* Creates an [AutoClearedValue] associated with this fragment. | |
*/ | |
fun <T : Any> Fragment.autoCleared() = AutoClearedValue<T>(this) |
class MainFragment : Fragment() { | |
private var viewBinding by autoCleared<FragmentMainBinding>() | |
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { | |
viewBinding = FragmentMainBinding.inflate(inflater, container, false) | |
return viewBinding.root | |
} | |
override fun onViewCreated(a_view: View, a_savedInstanceState: Bundle?) { | |
super.onViewCreated(a_view, a_savedInstanceState) | |
viewBinding.viewBinding.tvTitle.text = "Parkho" | |
} | |
} |
- dependecy 도 추가해야 한다.
dependencies { | |
implementation "androidx.lifecycle:lifecycle-runtime:2.2.0" | |
implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0" | |
// 필요에 따라...... | |
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0" | |
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0" | |
} |
◼ 라이브러리 사용하기
각 개발자들이 ViewBinding 을 편하게 사용하기 위해 만들어 놓은 library 를 사용하는 방식이다.
- Binding
'Android' 카테고리의 다른 글
원스토어(One Store)에 앱 등록하기 (0) | 2024.08.05 |
---|---|
보안정책 캡쳐 불가 화면에서 캡쳐하기 (6) | 2021.10.14 |
안드로이드 뷰 바인딩 (2) - 사용법 (0) | 2021.10.05 |
안드로이드 뷰 바인딩 (1) - 개요 및 다른 방식들과의 비교 (0) | 2021.09.24 |
Android 화면 녹화 (0) | 2021.08.31 |
- Total
- Today
- Yesterday
- 리워드 어플
- 안드로이드 서비스
- Intent
- Android Service
- onContextItemSelected
- 리워드앱
- android activity flag
- 앱테크 추천
- 앱테크
- 안드로이드 인텐트
- task 생성
- mPANDO
- StartService
- bindservice
- 무료 채굴
- 무료채굴
- task
- android flag activity
- onCreateContextMenu
- 채굴앱
- p2e
- notifyDataSetChanged
- WEMIX
- BroadcastReceiver
- M2E
- StringUtils
- registerForContextMenu
- android intent
- android task
- RoomDatabase
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |