Розробка дашборда аналітики мобільного приложення
Дашборд аналітики — не набір красивих графіків. Це інструмент прийняття рішень, і його цінність визначається тим, наскільки швидко користувач отримує відповідь на конкретне питання: «Де користувачі йдуть із воронки?», «Який сегмент приносить 80% виручки?», «Коли просів retention після останнього оновлення?». Відхилення від цього фокуса перетворює дашборд на декорацію.
Архітектурні рішення
Джерела даних та агрегація
Дашборд в мобільному приложенні рідко працює з сирими даними в реальному часі. Типова схема:
- OLAP-сховище для історичних даних: ClickHouse, BigQuery, Redshift — запити на мільйони рядків за секунди
- Кеш агрегатів: Redis з TTL для frequently-requested метрик (DAU, MAU, revenue today)
- Streaming для near-realtime: Kafka → ClickHouse Materialized Views
Якщо дашборд показує тільки агреговані метрики (без drill-down до конкретного користувача) — ClickHouse з попередньо обчисленими агрегатами дає затримку 50–200ms на запит при мільярді рядків.
Клієнтська архітектура
На Flutter — BLoC з окремими Cubits на кожен віджет дашборду, паралельне завантаження даних через Future.wait:
class DashboardBloc extends Bloc<DashboardEvent, DashboardState> {
final AnalyticsRepository _repository;
Future<void> _onLoadDashboard(LoadDashboard event, Emitter emit) async {
emit(DashboardLoading());
try {
final results = await Future.wait([
_repository.fetchDAU(event.dateRange),
_repository.fetchRevenue(event.dateRange),
_repository.fetchRetentionCohorts(event.dateRange),
_repository.fetchTopScreens(event.dateRange),
]);
emit(DashboardLoaded(
dau: results[0] as List<DailyActiveUsers>,
revenue: results[1] as RevenueMetrics,
retention: results[2] as RetentionCohorts,
topScreens: results[3] as List<ScreenMetrics>,
));
} catch (e) {
emit(DashboardError(e.toString()));
}
}
}
Паралельне завантаження критично: якщо 4 графіки завантажуються послідовно по 300ms — користувач чекає 1.2 секунди. Паралельно — 300ms.
Візуалізація: бібліотеки та вибір
| Бібліотека | Платформа | Сильні сторони | Обмеження |
|---|---|---|---|
fl_chart |
Flutter | Кастомізація, line/bar/pie/scatter | Немає candlestick, немає zoom |
syncfusion_flutter_charts |
Flutter | Багатий набір типів, zoom/pan | Комерційна ліцензія |
| Charts (Google) | Android | Native Material look | Слабка кастомізація |
| DGCharts | iOS | Swift-native, анімації | Тільки Swift/ObjC |
| Victory Native | RN | Декларативний API | Продуктивність при >5k точок |
Для аналітичних дашбордів з необхідністю zoom/pan та роботи з великою кількістю точок — syncfusion_flutter_charts або WebView з Echarts/Highcharts. WebView-підхід дає максимальну гнучкість, але додає overhead на комунікацію JS ↔ Dart.
Фільтри та інтерактивність
Фільтри за датою — найчастіший запит. DateTimeRange picker з пресетами (Сьогодні / 7 днів / 30 днів / Квартал / Рік) плюс кастомний діапазон. Важливо: при зміні фільтра потрібен debounce — не перезавантажувати дані при кожному тапу на діапазон:
// Debounce в StreamController або через rxdart
filterStream
.debounceTime(const Duration(milliseconds: 300))
.distinct()
.listen((filter) => bloc.add(UpdateFilter(filter)));
Drill-down — перехід від агрегату до деталей (тап на bar у графіку → список користувачів цього сегмента). Реалізується через роутинг з передачею контексту фільтра.
Експорт даних
Користувачі аналітичних дашбордів очікують можливість виходу. На мобільному — експорт у PDF та CSV.
PDF-генерація: на iOS PDFKit + UIGraphicsPDFRenderer, на Android PdfDocument. На Flutter — printing package з pdf package. Експорт скриншота графіка через RepaintBoundary + toImage():
Future<Uint8List?> captureChart(GlobalKey chartKey) async {
final boundary = chartKey.currentContext?.findRenderObject() as RenderRepaintBoundary?;
final image = await boundary?.toImage(pixelRatio: 2.0);
final byteData = await image?.toByteData(format: ImageByteFormat.png);
return byteData?.buffer.asUint8List();
}
CSV через csv package, відкриття через share_plus для передачі у пошту або Telegram.
Продуктивність при великому обсязі даних
Основна проблема дашбордів — деградація при великому часовому діапазоні. Графік DAU за рік — 365 точок, це нормально. Графік почасових подій за рік — 8760 точок, вже важко для рендерингу. Рішення: downsampling на сервері — повертаємо не більше N точок для поточного масштабу. При zoom in — завантажуємо більш детальні дані.
fl_chart при >500 точках у LineChart починає лагати на mid-range Android. Переключаємося на Canvas-рисування напряму через CustomPainter або використовуємо lossyDownsample алгоритм (Largest-Triangle-Three-Buckets) перед передачею даних у бібліотеку.
Етапи роботи
Аудит вимог та узгодження метрик → проектування API для агрегатів → настройка OLAP (якщо потрібно) → розробка UI компонентів → інтеграція → оптимізація продуктивності → публікація.
Строки
MVP з 5–8 метриками, лінійними графіками та фільтрами за датою: 3–5 тижнів. Повнофункціональний дашборд з drill-down, когортним аналізом, експортом та real-time метриками: 2–3 місяці. Вартість розраховується індивідуально після аналізу вимог.







