Coverage Summary for Class: ParentsBindingFragment (kr.open.library.simple_ui.xml.ui.components.fragment.binding)

Class Class, % Method, % Branch, % Line, % Instruction, %
ParentsBindingFragment 100% (1/1) 60% (6/10) 100% (4/4) 80% (16/20) 55.3% (78/141)


 package kr.open.library.simple_ui.xml.ui.components.fragment.binding
 
 import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import androidx.annotation.CallSuper
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import androidx.viewbinding.ViewBinding
 import kr.open.library.simple_ui.xml.ui.base.helper.ParentBindingHelperForFragment
 import kr.open.library.simple_ui.xml.ui.base.lifecycle.ParentBindingInterfaceForFragment
 import kr.open.library.simple_ui.xml.ui.components.fragment.root.RootFragment
 
 /**
  * Base Fragment with ViewBinding support and single-shot ViewModel event collection.<br>
  * Manages binding lifecycle safely and resets onDestroyView().<br><br>
  * ViewBinding 지원과 단일 ViewModel 이벤트 수집을 제공하는 기본 Fragment입니다.<br>
  * 바인딩 생명주기를 안전하게 관리하고 onDestroyView()에서 초기화합니다.<br>
  *
  * **Key points:**<br>
  * - Call super.onCreateView() and super.onViewCreated().<br>
  * - onEventVmCollect() is invoked once after binding initialization.<br>
  * - In Fragment, keeping the default `false` for isAttachToParent is recommended unless there is a verified special case.<br><br>
  * **핵심 포인트:**<br>
  * - super.onCreateView()와 super.onViewCreated()를 반드시 호출하세요.<br>
  * - onEventVmCollect()는 바인딩 초기화 이후 1회 호출됩니다.<br>
  * - Fragment에서는 특별한 경우가 아니라면 isAttachToParent의 기본값 `false` 사용을 권장합니다.<br>
  *
  * @param BINDING The type of ViewBinding to be used.<br><br>
  *                사용할 ViewBinding 타입.<br>
  * @param isAttachToParent Whether to attach the inflated view to the parent container.<br><br>
  *                         레이아웃을 부모 컨테이너에 attach할지 여부.<br>
  *                         Fragment에서는 특별한 경우가 아니라면 `false` 유지가 안전합니다.<br>
  */
 abstract class ParentsBindingFragment<BINDING : ViewBinding> :
     RootFragment,
     ParentBindingInterfaceForFragment<BINDING> {
     /**
      * Holds the ViewBinding instance for this Fragment.<br><br>
      * 이 Fragment의 ViewBinding 인스턴스를 보관합니다.<br>
      */
     private var binding: BINDING? = null
 
     private val isAttachToParent: Boolean
 
     constructor() : this(false)
     constructor(isAttachToParent: Boolean) {
         this.isAttachToParent = isAttachToParent
     }
 
     /**
      * Returns the initialized binding instance.<br>
      * Accessible only between onViewCreated() and onDestroyView().<br><br>
      * 초기화된 바인딩 인스턴스를 반환합니다.<br>
      * onViewCreated()와 onDestroyView() 사이에서만 접근하세요.<br>
      *
      * @return The initialized ViewBinding instance.<br><br>
      *         초기화된 ViewBinding 인스턴스.<br>
      *
      * @throws IllegalStateException If accessed after onDestroyView().<br><br>
      *                               onDestroyView() 이후 접근하면 예외가 발생합니다.<br>
      */
     protected fun getBinding(): BINDING {
         check(binding != null) {
             "Binding accessed after onDestroyView()"
         }
         return binding!!
     }
 
     /**
      * Helper to ensure one-time event collection for this Fragment instance.<br><br>
      * 이 Fragment 인스턴스에서 이벤트 수집을 1회만 보장하는 헬퍼입니다.<br>
      */
     private val helper = ParentBindingHelperForFragment()
 
     /**
      * Creates the ViewBinding instance.<br><br>
      * ViewBinding 인스턴스를 생성합니다.<br>
      *
      * @param inflater The LayoutInflater to inflate the binding.<br><br>
      *                 바인딩을 inflate할 LayoutInflater.<br>
      * @param container The parent container, if any.<br><br>
      *                  부모 컨테이너(있다면).<br>
      * @param isAttachToParent Whether to attach to the parent.<br><br>
      *                         부모에 attach할지 여부.<br>
      *                         Fragment에서는 특별한 경우가 아니라면 `false` 유지가 안전합니다.<br>
      * @return The initialized ViewBinding instance.<br><br>
      *         초기화된 ViewBinding 인스턴스.<br>
      */
     protected abstract fun createBinding(inflater: LayoutInflater, container: ViewGroup?, isAttachToParent: Boolean): BINDING
 
     @CallSuper
     final override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
         binding = createBinding(inflater, container, isAttachToParent)
         onBindingCreated(getBinding(), savedInstanceState)
         return getBinding().root
     }
 
     @CallSuper
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super<RootFragment>.onViewCreated(view, savedInstanceState)
         onViewCreated(getBinding(), savedInstanceState)
         helper.startEventVmCollect { onEventVmCollect(getBinding()) }
     }
 
     /**
      * Cleans up binding and resets helper state.<br>
      * Always call super.onDestroyView().<br><br>
      * 바인딩을 정리하고 헬퍼 상태를 초기화합니다.<br>
      * 반드시 super.onDestroyView()를 호출하세요.<br>
      */
     @CallSuper
     override fun onDestroyView() {
         super.onDestroyView()
         helper.reset()
         binding = null
     }
 
     /**
      * Obtains a ViewModel of the specified type using ViewModelProvider.<br><br>
      * ViewModelProvider로 지정한 타입의 ViewModel을 가져옵니다.<br>
      *
      * @param T The type of the ViewModel to obtain.<br><br>
      *          가져올 ViewModel 타입.<br>
      * @return The ViewModel instance of type T.<br><br>
      *         T 타입의 ViewModel 인스턴스.<br>
      */
     protected inline fun <reified T : ViewModel> getViewModel(): T =
         ViewModelProvider(this, defaultViewModelProviderFactory)[T::class.java]
 
     /**
      * Obtains a ViewModel of the specified type using ViewModelProvider with a custom factory.<br><br>
      * 커스텀 Factory로 지정한 타입의 ViewModel을 가져옵니다.<br>
      *
      * @param T The type of the ViewModel to obtain.<br><br>
      *          가져올 ViewModel 타입.<br>
      * @param factory The Factory to use for creating the ViewModel instance.<br><br>
      *                ViewModel 생성에 사용할 Factory.<br>
      * @return The ViewModel instance of type T.<br><br>
      *         T 타입의 ViewModel 인스턴스.<br>
      */
     protected inline fun <reified T : ViewModel> getViewModel(factory: ViewModelProvider.Factory): T =
         ViewModelProvider(this, factory)[T::class.java]
 
     /**
      * Obtains a ViewModel scoped to the parent Activity.<br>
      * Use this to share a ViewModel between Fragments and their host Activity.<br><br>
      * 부모 Activity 스코프의 ViewModel을 가져옵니다.<br>
      * Fragment와 호스트 Activity 간 ViewModel을 공유할 때 사용하세요.<br>
      *
      * @param T The type of the ViewModel to obtain.<br><br>
      *          가져올 ViewModel 타입.<br>
      * @return The ViewModel instance of type T scoped to the parent Activity.<br><br>
      *         부모 Activity 스코프의 T 타입 ViewModel 인스턴스.<br>
      *
      * @throws IllegalStateException If the Fragment is not attached to an Activity.<br><br>
      *                               Fragment가 Activity에 attach되지 않은 경우 예외가 발생합니다.<br>
      */
     protected inline fun <reified T : ViewModel> getActivityViewModel(): T =
         ViewModelProvider(requireActivity(), requireActivity().defaultViewModelProviderFactory)[T::class.java]
 
     /**
      * Obtains a ViewModel scoped to the parent Activity with a custom factory.<br><br>
      * 커스텀 Factory로 부모 Activity 스코프의 ViewModel을 가져옵니다.<br>
      *
      * @param T The type of the ViewModel to obtain.<br><br>
      *          가져올 ViewModel 타입.<br>
      * @param factory The Factory to use for creating the ViewModel instance.<br><br>
      *                ViewModel 생성에 사용할 Factory.<br>
      * @return The ViewModel instance of type T scoped to the parent Activity.<br><br>
      *         부모 Activity 스코프의 T 타입 ViewModel 인스턴스.<br>
      *
      * @throws IllegalStateException If the Fragment is not attached to an Activity.<br><br>
      *                               Fragment가 Activity에 attach되지 않은 경우 예외가 발생합니다.<br>
      */
     protected inline fun <reified T : ViewModel> getActivityViewModel(factory: ViewModelProvider.Factory): T =
         ViewModelProvider(requireActivity(), factory)[T::class.java]
 }