← Назад к вопросам

Как Observer уведомляет объекты

1.3 Junior🔥 201 комментариев
#Архитектура и паттерны#Многопоточность и асинхронность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Observer Pattern (Паттерн Наблюдатель)

Observer (Наблюдатель) — это поведенческий паттерн проектирования, который обеспечивает механизм подписки на изменения. Когда состояние объекта меняется, все подписчики автоматически об этом уведомляются. Это основа реактивного программирования в Android.

Основная идея

Шаблон Observer состоит из двух ключевых участников:

  • Subject (Издатель/Observable) — объект, за состоянием которого наблюдают
  • Observer (Наблюдатель) — объект, который хочет узнать об изменениях

Когда Subject изменяется, он уведомляет всех Observer'ов через вызов их методов обратного вызова.

Механизм уведомления

// Шаг 1: Observer регистрируется (подписывается)
observer.subscribe(subject)

// Шаг 2: Subject меняет своё состояние
subject.setState(newValue)

// Шаг 3: Subject уведомляет всех Observer'ов
subject.notifyObservers()  // вызывает update() на каждом observer

// Шаг 4: Каждый Observer реагирует на изменение
observer.update(newValue)

Классический пример реализации

// Интерфейс Observer
interface Observer {
    fun update(newValue: String)
}

// Subject - издатель
class DataStore {
    private var data: String = ""
    private val observers = mutableListOf<Observer>()
    
    // Метод для подписки
    fun subscribe(observer: Observer) {
        observers.add(observer)
    }
    
    // Метод для отписки
    fun unsubscribe(observer: Observer) {
        observers.remove(observer)
    }
    
    // Изменение состояния
    fun setState(newValue: String) {
        data = newValue
        notifyObservers()  // уведомляем всех
    }
    
    // Уведомление всех подписчиков
    private fun notifyObservers() {
        for (observer in observers) {
            observer.update(data)  // вызываем update() на каждом
        }
    }
}

// Конкретный Observer
class UIObserver(val name: String) : Observer {
    override fun update(newValue: String) {
        println("$name получил обновление: $newValue")
    }
}

// Использование
val store = DataStore()
val ui1 = UIObserver("UI1")
val ui2 = UIObserver("UI2")

store.subscribe(ui1)
store.subscribe(ui2)

store.setState("Hello")  // оба observer'а получат уведомление
// Вывод:
// UI1 получил обновление: Hello
// UI2 получил обновление: Hello

Observer в Android (современный подход с LiveData)

class UserViewModel : ViewModel() {
    // LiveData автоматически уведомляет Observer'ов
    private val _userLiveData = MutableLiveData<User>()
    val userLiveData: LiveData<User> = _userLiveData
    
    fun loadUser(userId: String) {
        viewModelScope.launch {
            val user = userRepository.getUser(userId)
            _userLiveData.value = user  // уведомляет всех Observer'ов
        }
    }
}

// В Activity/Fragment
class UserActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val viewModel = ViewModelProvider(this).get(UserViewModel::class.java)
        
        // Observer подписывается на изменения
        viewModel.userLiveData.observe(this) { user ->
            // Автоматически вызывается при изменении userLiveData
            displayUser(user)
        }
        
        viewModel.loadUser("123")
    }
}

Observer с RxJava (реактивный подход)

// Observable - это наблюдаемый объект
val numberObservable: Observable<Int> = Observable.create { emitter ->
    emitter.onNext(1)
    emitter.onNext(2)
    emitter.onNext(3)
    emitter.onComplete()
}

// Observer подписывается
numberObservable.subscribe(
    { value -> println("Получено: $value") },      // onNext
    { error -> println("Ошибка: $error") },        // onError
    { println("Завершено") }                        // onComplete
)

// или с использованием оператора filter
numberObservable
    .filter { it % 2 == 0 }
    .subscribe { value -> println("Чётное: $value") }

Observer с Flow (Kotlin Coroutines)

class DataRepository {
    private val _stateFlow = MutableStateFlow<String>("Initial")
    val stateFlow: StateFlow<String> = _stateFlow.asStateFlow()
    
    fun updateData(newValue: String) {
        _stateFlow.value = newValue  // уведомляет всех подписчиков
    }
}

// В ViewModel
class DataViewModel(private val repo: DataRepository) : ViewModel() {
    fun observeData() {
        viewModelScope.launch {
            repo.stateFlow.collect { value ->
                // Вызывается каждый раз при изменении
                println("Data: $value")
            }
        }
    }
}

Поток выполнения уведомления

1. Subject меняет состояние
   ↓
2. Subject вызывает notifyObservers()
   ↓
3. notifyObservers() итерирует по списку Observer'ов
   ↓
4. Для каждого Observer вызывает observer.update()
   ↓
5. Каждый Observer реагирует на изменение (обновляет UI, логику и т.д.)

Схема взаимодействия

┌─────────────┐
│   Subject   │
│  (состояние)│
└──────┬──────┘
       │
       │ subscribe()
       ├─────────┬──────────┬──────────┐
       ↓         ↓          ↓          ↓
   Observer1  Observer2  Observer3  Observer4
   (UI1)      (Logger)   (Database) (Analytics)
       ↑         ↑          ↑          ↑
       └─────────┼──────────┼──────────┘
              setState()
              → notifyObservers()

Преимущества Pattern

Слабая связанность — Subject не знает деталей Observer'ов

Динамическая подписка — Observer'ы могут подписаться/отписаться во время выполнения

Множественная уведомления — одно изменение → все Observer'ы уведомлены

Реактивность — автоматические обновления при изменении состояния

Недостатки

Порядок уведомления — не гарантирован порядок вызова Observer'ов

Performance — много Observer'ов → много уведомлений

Утечки памяти — забытые подписки могут держать объекты в памяти

Best Practices

Всегда отписывайся — отписывайся от Observer при уничтожении объекта

// Плохо - может быть утечка памяти
viewModel.userLiveData.observe(this) { user ->
    displayUser(user)
}

// Хорошо - LiveData автоматически отписывает lifecycle-aware
// (это уже работает с observe())

Используй lifecycle-aware компоненты — LiveData, StateFlow с viewModelScope

Избегай блокирующих операций в observer.update()

Современные альтернативы

ПодходКогда использовать
LiveDataActivity/Fragment, простые случаи
StateFlowViewModel, реактивный подход
FlowАсинхронные операции, stream обработки
RxJavaСложная реактивная логика

Заключение

Observer Pattern — фундаментальный паттерн для уведомления об изменениях. Современный Android использует LiveData и Flow вместо классической реализации, но принцип остаётся неизменным: Subject уведомляет всех зарегистрированных Observer'ов через вызов их callback методов. Это основа реактивного программирования и MVC архитектуры в Android.

Как Observer уведомляет объекты | PrepBro