> Как реализовать работу в фоне во Flutter для отправки данных при возобновлении связи (Flutter, Android)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: PashaPay
Стек: Flutter, Android
> Пример ответа
Короткий ответ
Для фоновой отправки данных при возобновлении связи во Flutter используйте комбинацию connectivity_plus для мониторинга сети и workmanager или flutter_background_service для выполнения задачи в фоне. Ключевой момент - не полагаться только на lifecycle-методы, так как ОС может убить процесс. На Android надёжнее использовать WorkManager с периодическим запуском и проверкой состояния сети, либо BroadcastReceiver на CONNECTIVITY_CHANGE через нативный код, если нужна мгновенная реакция.
Подробное объяснение
Задача сводится к трём аспектам: детекция восстановления связи, выполнение кода в фоне и гарантия доставки данных. Во Flutter нет прямого доступа к системным событиям сети, поэтому используются плагины.
Основные подходы:
-
connectivity_plus+WidgetsBindingObserver- работает только пока приложение активно или в фоне, но не после убийства процесса. Подходит для простых сценариев, но не гарантирует выполнение при свёрнутом приложении на Android. -
workmanager- обёртка над AndroidWorkManagerи iOSBGTaskScheduler. Позволяет регистрировать периодические задачи (минимум 15 минут на Android) или отложенные задачи с условиемNetworkType.CONNECTED. Это самый надёжный способ для отправки данных: система сама запустит задачу при появлении сети, даже если приложение убито. -
flutter_background_service- запускает долгоживущий изолят, но требует осторожности: Android ограничивает фоновые процессы, и такой подход быстрее приводит к батарейным проблемам. Используйте только если нужен постоянный мониторинг. -
Нативный
BroadcastReceiverнаCONNECTIVITY_CHANGE- самый мгновенный отклик, но требует написания Kotlin/Java кода и передачи данных черезMethodChannelилиEventChannel.
Для отправки данных при возобновлении связи оптимальная связка: workmanager с условием NetworkType.CONNECTED + локальное хранилище (shared_preferences, sqflite, hive) для очереди неотправленных данных. Приложение пишет данные в очередь, а фоновая задача забирает их и отправляет на сервер.
На практике
- Создайте очередь данных в локальном хранилище. Каждая запись - JSON с payload и метаданными.
- Зарегистрируйте фоновую задачу через
Workmanager().registerPeriodicTaskилиregisterOneOffTaskсNetworkType.CONNECTED. - В callback задачи читайте очередь, отправляйте данные, удаляйте успешно отправленные.
- Для мгновенной реакции при активном приложении подпишитесь на стрим
Connectivity().onConnectivityChangedи вызывайте ту же функцию отправки. - Обязательно обработайте ошибки сети и повторы - задача должна быть идемпотентной.
На Android 12+ добавьте разрешения INTERNET, ACCESS_NETWORK_STATE, RECEIVE_BOOT_COMPLETED (для перезапуска после перезагрузки). Для workmanager укажите android:enableWorkManager в манифесте.
Пример кода
// main.dart void main() async { WidgetsFlutterBinding.ensureInitialized(); await Workmanager().initialize(callbackDispatcher); Workmanager().registerPeriodicTask( 'sync-task', 'syncData', frequency: Duration(minutes: 15), constraints: Constraints(networkType: NetworkType.CONNECTED), ); runApp(MyApp()); } // Фоновая задача void callbackDispatcher() { Workmanager().executeTask((task, inputData) async { if (task == 'syncData') { await sendPendingData(); } return true; }); } Future<void> sendPendingData() async { final queue = await LocalQueue().getPending(); for (final item in queue) { try { await ApiClient().send(item.payload); await LocalQueue().remove(item.id); } catch (e) { // оставляем в очереди, попробуем в следующий раз } } } // В UI - мгновенная отправка при появлении сети Connectivity().onConnectivityChanged.listen((result) { if (result != ConnectivityResult.none) { sendPendingData(); } });
Как отвечать на собеседовании
Начните с уточнения требований: нужно ли отправлять после убийства приложения, какой допустимый интервал задержки, какой объём данных. Это покажет системное мышление. Затем опишите два уровня: активный (стрим connectivity) и фоновый (workmanager). Подчеркните trade-off: workmanager не мгновенный, но надёжный; BroadcastReceiver - мгновенный, но сложнее. Упомяните, что на iOS подходы отличаются (BGTaskScheduler, ограничения по времени). Если спросят про гарантию доставки - говорите про очередь и идемпотентность, а не про "просто отправку".
Что проверяет интервьюер
- Понимание lifecycle Android и ограничений фоновых процессов.
- Умение выбирать инструмент под задачу, а не использовать первый попавшийся плагин.
- Знание, как работает WorkManager: условия, периодичность, гарантии выполнения.
- Умение проектировать отказоустойчивую отправку: очередь, ретраи, обработка ошибок.
- Осознание различий между платформами (Android vs iOS).
Типичные ошибки
- Использование только
connectivity_plusвinitState- после убийства приложения ничего не отправится. - Запуск
flutter_background_serviceбез необходимости - быстрый расход батареи и возможный бан от Google Play. - Отправка данных прямо в callback без очереди - потеря данных при сбое сети.
- Игнорирование
NetworkType.CONNECTEDв constraints - задача будет запускаться без сети и падать. - Необработка ошибок в фоновой задаче - возврат
falseизexecuteTaskприведёт к повторным попыткам и лишнему расходу ресурсов.
> Похожие задачи по mobile
В чем плюсы и минусы Kotlin Multiplatform по сравнению с Flutter?
Как во Flutter взаимодействовать с нативным кодом платформы для обмена данными
Какие методы жизненного цикла приложения во Flutter используются для отслеживания сворачивания и разворачивания
Какие пакеты для локального хранения данных во Flutter использовать
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью