This document describes the high-level architecture of the Heart Rate Monitor app.
graph TD
subgraph UI_Layer
Compose[Jetpack Compose UI]
VM[ViewModels]
end
subgraph Domain_Core_Layer
HRE[HeartRate Engine]
CSI[CameraSupport Interface]
PS[Processing Engine]
end
subgraph Data_Layer
Repo[HistoryRepository]
Room[Room Database]
end
subgraph Hardware
Cam[Device Camera]
end
%% UI to ViewModel
Compose --> VM
%% ViewModel to Repository and Engine
VM --> Repo
VM --> HRE
%% Engine to Camera and Processing
HRE --> CSI
CSI --> PS
CSI --> Cam
%% Repository to Database
Repo --> Room
- Jetpack Compose: Uses a modern declarative approach to build the UI.
- ViewModels: Use
StateFlowto expose state to the UI andviewModelScopefor asynchronous operations. - Hilt: Handles dependency injection for ViewModels.
- HeartRate Engine: Manages the lifecycle of a measurement (start, stop, timer). It implements the
PreviewListenerto receive data from the camera. - CameraSupport: A hardware abstraction layer. Currently implemented using CameraX, but can be swapped easily due to its interface-based design.
- Processing Engine: Specialized logic that converts camera frames into "redness" values used for pulse detection.
- HistoryRepository: The single source of truth for heart rate history data.
- Room Database: Handles local persistence of history models.
- User Action: User taps "Start" in the UI.
- ViewModel: Updates state to
isStarted = trueand callsHeartRate.startPulseCheck(). - Engine: Opens the camera and starts a timer.
- Hardware/Core: Camera frames are processed; the engine calculates BPM and emits results via a listener.
- ViewModel: Receives BPM updates and pushes them to the UI via
beatsPerMinuteStateFlow. - Persistence: Upon completion, the user can save the result, which flows through the ViewModel to the Repository and into the Room database.