Observer Pattern?
Observer Pattern은 객체 간 일대다 관계를 통해 한 객체의 상태가 변경될 때 이를 자동으로 통지하고 구독 중인 객체들이 변화에 반응하도록 하는 디자인 패턴이며, 핵심 구성요소로 Subject(주체)와 Observer(관찰자)가 있다.
Subject는 상태가 변할 때 Observer에게 변경 사항을 통지하고, Observer는 이를 자동으로 반응한다.
이 패턴은 데이터의 변화에 따라 UI 업데이트나 로직을 자동으로 수행하게 만들어 데이터의 일관성을 유지하고 코드간의 결합도를 낮출 수 있다.
Android에서는 LiveData, Flow, RxJava 등을 통해 Observer Pattern을 쉽게 구현할 수 있다.
특히, MVVM 구조에서 ViewModel이 LiveData를 통해 Activity나 Fragment와 데이터를 연동해 UI와 데이터 변경을 자동화하는 데 활용된다.
옵저버 패턴을 적용하면서 UI업데이트 로직을 간소화 하면서 메인스레드에서 안전하게 데이터 관찰이 가능해 효율적인 상태관리에 기여한다.
class UserViewModel : ViewModel() {
private val repository: UserRepository = UserRepository()
val userFlow: Flow<List<User>> = repository.getUsers()
.flowOn(Dispatchers.IO) // IO스레드에서 실행
.catch { emit(emptyList()) } // 빈 리스트 방출
}
Flow는 Kotlin Coroutines에서 제공하는 비동기 스트림으로, Observer Pattern을 구현할 때 효과적이다.
class UserActivity : AppCompatActivity() {
private val viewModel: UserViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user)
lifecycleScope.launch {
viewModel.userFlow.collect { users ->
userAdapter.submitList(users)
}
}
}
}
Activity에서는 lifecycleScope.launch를 사용해 Flow를 수집하고(collect) 데이터가 변경될 때마다 UI를 업데이트한다.
lifecycleScope는 Activity의 생명주기에 맞춰 Flow를 구독하므로, Activity가 보이는 상태에서만 데이터를 수신하며, 자동으로 중지되어 메모리 누수를 방지한다.
네트워크 상태 모니터링
interface ConnectivityObserver {
val networkStatus: Flow<NetworkStatus>
enum class NetworkStatus { Available, Unavailable }
}
네트워크 상태 변화를 Flow 형태로 제공하기 위한 Interface
class ConnectivityObserverImpl(context: Context) : ConnectivityObserver {
private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
override val networkStatus: Flow<NetworkStatus> = callbackFlow {
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
trySend(NetworkStatus.Available)
}
override fun onLost(network: Network) {
trySend(NetworkStatus.Unavailable)
}
}
connectivityManager.registerDefaultNetworkCallback(callback)
awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
}.distinctUntilChanged()
}
• ConnectivityObserverImpl은 ConnectivityManager를 통해 네트워크 상태를 callbackFlow로 변환하여 Flow 형태로 제공.
• 네트워크가 연결되면 onAvailable, 끊기면 onLost가 호출되어 NetworkStatus 값을 trySend로 전송.
• awaitClose로 callbackFlow가 닫힐 때 NetworkCallback을 해제해 리소스를 절약.
• distinctUntilChanged()로 동일 상태의 중복 업데이트를 방지.
class UserActivity : AppCompatActivity() {
private val connectivityObserver: ConnectivityObserver = ConnectivityObserverImpl(this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user)
lifecycleScope.launch {
connectivityObserver.networkStatus.collect { status ->
when (status) {
NetworkStatus.Available -> showOnlineUI()
NetworkStatus.Unavailable -> showOfflineUI()
}
}
}
}
}
• Activity는 lifecycleScope를 사용해 networkStatus를 구독.
collect를 호출해 networkStatus가 변화할 때마다 status 값을 수신하여 이를 기반으로 UI를 업데이트 처리.
• lifecycleScope는 Activity의 생명주기와 연동되어 있어, Activity가 종료되면 Flow 구독도 자동으로 해제되므로 메모리 누수를 방지.