Разработка дашборда аналитики мобильного приложения
Дашборд аналитики — не набор красивых графиков. Это инструмент принятия решений, и его ценность определяется тем, насколько быстро пользователь получает ответ на конкретный вопрос: «Где пользователи уходят из воронки?», «Какой сегмент приносит 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 с сeparate 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 месяца. Стоимость рассчитывается индивидуально после анализа требований.







