Coverage Summary for Class: BaseViewModelEvent (kr.open.library.simple_ui.core.viewmodel)

Class Method, % Branch, % Line, % Instruction, %
BaseViewModelEvent 100% (3/3) 100% (6/6) 100% (43/43)
BaseViewModelEvent$sendEventVm$1 100% (1/1) 100% (1/1) 100% (25/25)
Total 100% (4/4) 100% (7/7) 100% (68/68)


 package kr.open.library.simple_ui.core.viewmodel
 
 import androidx.lifecycle.viewModelScope
 import kotlinx.coroutines.channels.Channel
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.receiveAsFlow
 import kotlinx.coroutines.launch
 
 /**
  * Base ViewModel class with event handling capability using Kotlin Flows.<br>
  * Provides a unidirectional communication channel from ViewModel to View (Activity, Fragment, or CustomView).<br><br>
  * Kotlin Flow를 사용한 이벤트 처리 기능을 갖춘 기본 ViewModel 클래스입니다.<br>
  * ViewModel에서 View(Activity, Fragment 또는 CustomView)로의 단방향 통신 채널을 제공합니다.<br>
  *
  * Features:<br>
  * - Type-safe event emission using generics<br>
  * - Buffered channel for reliable event delivery<br>
  * - Automatic channel cleanup on ViewModel destruction<br>
  * - Lifecycle-aware event observation<br><br>
  * 기능:<br>
  * - 제네릭을 사용한 타입 안전 이벤트 발행<br>
  * - 안정적인 이벤트 전달을 위한 버퍼링된 채널<br>
  * - ViewModel 소멸 시 자동 채널 정리<br>
  * - 생명주기 인식 이벤트 관찰<br>
  *
  * Usage example:<br>
  * ```kotlin
  * // Define event types
  * sealed class MyEvent {
  *     data class ShowToast(val message: String) : MyEvent()
  *     object NavigateToHome : MyEvent()
  *     data class ShowError(val error: Throwable) : MyEvent()
  * }
  *
  * // Create ViewModel
  * class MyViewModel : BaseViewModelEvent<MyEvent>() {
  *     fun onButtonClick() {
  *         sendEventVm(MyEvent.ShowToast("Button clicked!"))
  *     }
  *
  *     fun onLoginSuccess() {
  *         sendEventVm(MyEvent.NavigateToHome)
  *     }
  * }
  *
  * // Observe events in Activity/Fragment
  * class MyActivity : AppCompatActivity() {
  *     private val viewModel: MyViewModel by viewModels()
  *
  *     override fun onCreate(savedInstanceState: Bundle?) {
  *         super.onCreate(savedInstanceState)
  *
  *         lifecycleScope.launch {
  *             repeatOnLifecycle(Lifecycle.State.STARTED) {
  *                 viewModel.eventVmFlow.collect { event ->
  *                     when (event) {
  *                         is MyEvent.ShowToast -> showToast(event.message)
  *                         is MyEvent.NavigateToHome -> navigateToHome()
  *                         is MyEvent.ShowError -> showError(event.error)
  *                     }
  *                 }
  *             }
  *         }
  *     }
  * }
  * ```
  * @param EVENT_TYPE The type of events this ViewModel can emit. Sealed classes are recommended for type safety.<br><br>
  *                   이 ViewModel이 발행할 수 있는 이벤트 타입. 타입 안전성을 위해 sealed class를 권장합니다.<br>
  *
  * @see BaseViewModel For ViewModel without event handling capability.<br><br>
  *      이벤트 처리 기능이 없는 ViewModel은 BaseViewModel을 참조하세요.<br>
  */
 public abstract class BaseViewModelEvent<EVENT_TYPE> : BaseViewModel() {
     /**
      * Private channel for sending events from ViewModel to View.<br>
      * Uses buffered channel to prevent event loss when collector is not ready.<br><br>
      * ViewModel에서 View로 이벤트를 보내기 위한 private 채널입니다.<br>
      * 수집기가 준비되지 않았을 때 이벤트 손실을 방지하기 위해 버퍼링된 채널을 사용합니다.<br>
      */
     private val eventVm = Channel<EVENT_TYPE>(Channel.BUFFERED)
 
     /**
      * Public Flow for observing events in View layer.<br>
      * single-consumer; multiple collectors may miss events. Use a single collector or switch to SharedFlow if you need multicast.<br>
      * This event channel is intended for UI one-off events (e.g., navigation, toast). Avoid using it for high-frequency streams (timer/sensor/state), as it may cause backpressure or UI delay.<br>
      * Collect this flow in Activity, Fragment, or CustomView to receive events from ViewModel.<br><br>
      * View 레이어에서 이벤트를 관찰하기 위한 public Flow입니다.<br>
      * 단일 소비자 기반이라 다중 수집 시 이벤트가 누락될 수 있습니다. 단일 수집을 권장하며, 멀티캐스트가 필요하면 SharedFlow로 전환하세요.<br>
      * 이 이벤트 채널은 내비게이션·토스트 같은 단발 UI 이벤트 용도입니다. 타이머/센서/상태 갱신처럼 고빈도 스트림에는 부적합하며, 백프레셔나 UI 지연이 발생할 수 있습니다.<br>
      * ViewModel로부터 이벤트를 받으려면 Activity, Fragment 또는 CustomView에서 이 flow를 수집하세요.<br>
      */
     public val eventVmFlow: Flow<EVENT_TYPE> = eventVm.receiveAsFlow()
 
     /**
      * Sends an event to the View layer through the event channel.<br>
      * Uses viewModelScope to launch a coroutine for sending the event.<br><br>
      * 이벤트 채널을 통해 View 레이어로 이벤트를 보냅니다.<br>
      * viewModelScope를 사용하여 이벤트 전송을 위한 코루틴을 실행합니다.<br>
      *
      * @param event The event to send to the View.<br><br>
      *              View로 보낼 이벤트.<br>
      */
     protected fun sendEventVm(event: EVENT_TYPE) {
         viewModelScope.launch { eventVm.send(event) }
     }
 
     /**
      * Called when this ViewModel is no longer used and will be destroyed.<br>
      * Closes the event channel to prevent memory leaks and ensure proper resource cleanup.<br><br>
      * 이 ViewModel이 더 이상 사용되지 않고 소멸될 때 호출됩니다.<br>
      * 메모리 누수를 방지하고 적절한 리소스 정리를 보장하기 위해 이벤트 채널을 닫습니다.<br>
      */
     override fun onCleared() {
         super.onCleared()
         eventVm.close()
     }
 }