Фоновые задачи Flutter
Фоновые задачи Flutter

Исходный адрес: Flutter Background Tasks


Flutter — это очень простая в использовании платформа для создания красивых мобильных приложений с использованием языка программирования Dart, позволяющая использовать один и тот же набор кода на Android и IOS.

Мобильным приложениям может потребоваться выполнение фоновых задач, таких как отслеживание изменений местоположения, отслеживание движений пользователя (шаги, бег, ходьба, вождение и т. д.), подписка на системные события, такие как BootComplete, заряд батареи и зарядка, поиск сетей BT или WiFi, и т. д.

В Android мы можем запускать некоторые фоновые задачи, пока приложение фактически закрыто!

Сначала определите приемник широковещательной рассылки BootComplete, который будет выполняться сразу после запуска телефона. Затем используйте WorkManager или AlarmManager для планирования фоновых задач и используйте Service для выполнения кода в фоновом режиме.

Конечно, некоторые фоновые задачи требуют разрешений пользователя и могут отображать уведомление на панели уведомлений, указывающее, что приложение работает в фоновом режиме. Эти задачи могут выполняться в фоновом режиме, если пользователь знает и согласен.

В iOS фоновые задачи более строгие, но способы запуска некоторых фоновых задач все же есть.

Что касается Flutter-приложений и фоновых задач, то необходимо уточнить, что они выполняются на противоположной платформе! Логика, отвечающая за регистрацию и управление фоновыми задачами (Worker, Alarm, Service, BroadcastReceiver и т. д.), написана на собственном коде, например Kotlin или Swift. Однако мы все знаем, что логика приложения Flutter написана на стороне Dart, и эти коды могут создавать пользовательский интерфейс, а также управлять постоянными данными, управлением пользователями, сетевой инфраструктурой и токенами и т. д.

Если мы хотим обмениваться данными между Dart и собственной стороной, мы можем использовать Flutter MethodChannel и EventChannel.

Во Flutter MethodChannel и EventChannel — это способы отправки и получения информации с локальной стороны на сторону Dart. Они используются в плагинах Flutter.

Предположим, нас интересуют данные BootComplete и состояние батареи, и мы хотим использовать Dart для обработки этих событий в фоновом режиме.

Обычно, когда приложение находится на переднем плане, между стороной Dart и собственной стороной легко взаимодействовать через MethodChannel и EventChannel, но что, если вы хотите запустить Dart с собственной стороны и запустить фоновую изоляцию?

Давайте узнаем!

Прежде чем приступить к статье ниже, я настоятельно рекомендую вам ознакомиться с Flutter Плагины и способы их создания, поскольку пример будет основан на Flutter реализация плагина,Посмотреть подробностидокумент

Запустите движок Dart (из серверной части)

Когда приложение запускается, Flutter из main изолировать (точку входа) существует основная (основная) функция в запуске. К счастью, кажется, что его также можно купить в местных магазинах. Dart ВМ, и на заднем плане isolate(дополнительная точка входа)позвонитьглобальная функция

Dart VM Запуск можно выполнить не только из main Вход запускается, или это могут быть другие входы, например фоновый isolate изглобальная функция

Ключ существования к приложению За кулисами просыпаются, местная сторона удерживает доступную точку входа из(глобальная Функция) идентификатор ссылки — callbackRawHandle

ChatGPT сообщает о Dart CallbackRawHandle

существовать Dart середина,“callback raw handle”да对 Dart Базовая реализация функции может быть перенесена на родную платформу. API。 callbackRawHandle позволяет обойти Dart VM изобщая проверка типа,Вызывается напрямую из собственного кодафункция。Это полезно, когда вам нужно передать функцию Dart в качестве обратного вызова в собственную библиотеку.callbackRawHandle Сценарий использования: приложение локальнозавершить. вызов Dart код.

Чтобы запустить из локального фона Dart код,Требуется несколько шагов,существования Подробности перед введением кода,Я хочу показать это с помощью графика,Тогда объясните:

Давайте посмотрим на эту диаграмму и объясним каждую часть, поскольку вы можете видеть, что существует шесть основных шагов:

  1. существовать Dart Определить без параметров callbackDispatcher глобальная функция,это Волякакдополнительная точка входасуществовать За кулисами. Запуск изолированно и напрямую из локальных цепочек. вызов。
  2. Эта часть также состоит из трех этапов:
  • когда приложение запускается в первый раз,ВоляcallbackDispatcherфункциячерез api из параметра, переданного в плагин
  • существоватьплагинсередина,использовать PluginUtils::toRawHandle генерация метода callbackDispatcherизRawHandle,и пройти MethodChannel Воля его переадресации приезжатьплагинизировать местный конец (2').

Вышеупомянутый процесссуществовать Dart сторона.

  • Воля RawHandle Значение (длинное целое число) сохраняется в локальном постоянном хранилище, чтобы его мог использовать Воля. — 2’’

long Ценность можно понимать как Dart Адрес памяти функции обратного вызова передается на локальный конец.

После того, как вышеуказанная часть может быть завершена,нас ВоляRawHandleдержатьсуществовать持久存储середина,когдаприложениесуществовать За кулисами Когда проснешься, оно на складе RawHandle Доступен и Воля используется непосредственно из местных текстур. вызовcallbackDispatcher

  1. когдаприложениесуществовать За кулисами Когда просыпаешься(примернравиться:запускать Заканчивать-За инициализатор процесса кулисами), полученный из постоянного хранилища RawHandle。
  2. существовать За кулисамиинициализацияFlutterEngineиFlutterLoader

5. Пройти RawHandle ПолучатьFlutterCallbackInfo

  1. использоватьDartExecutorиcallbackInfo(来自Нет. 5 步)вызовexecuteDartCallback。这样就可以вызовсуществовать Dart сторонаизcallbackDispatcherфункция Понятно。
  2. когда callbackDispatcher При вызове вы можете зарегистрировать другое событие существования и За в ствоватьплагин. кулисамииз Dart Держите их рядом или используйте другие!

В собственных плагинах вы можете вызывать код на стороне Dart через дескриптор функции Dart, а также использовать другие плагины через дескриптор.

нравитьсяупомянутый выше,callbackDispatcher только Dart За кулисамиизоляция от входа.

Давайте разобьем описанные выше шаги на примеры кода:

Создайте диспетчер обратного вызова callbackDispatcher в main.dart.

существуют во фрагменте кода выше,существовать main.dart Создано в ПонятноПриложениеCallbackDispatcherглобальная Функция, это Воля становится Dart конециздополнительная точка входа,Может быть назван непосредственно существующим локально,исуществовать За кулисами Бег в изоляции.

Поймите: глобальная функция,бегатьсуществовать За кулисами нитки. Уведомление @pragma('vm:entry-point') Комментарии обязательны, поскольку данная функциясуществовать Dart На стороне вызова нет (вызывается напрямую с локального), поэтому AOT tree-shaking Компилятор может удалить эту функцию при создании сборки. Эта аннотация не позволяет компилятору удалить эту функцию.

Давайте повернем его боком и посмотрим, как это выглядит:

Получите RawHandle в коде Dart плагина

существуя из приведенного выше примера кода, мы можем видеть, как Flutter плагин Dart конец。Здесь интересноиздаregisterCallbackDispatcher API,этода从приложениеизИспользуйте callbackDispatcher в функции main().作为参数вызовиз API。Затем,существовать Нет. 13 приезжать 15 ОК, используйPluginUtilitiesи toRawHandle()方法Получать其RawHandle

Затем,существовать Нет. 17 ОК, используй methodChannel Воля его переадресует приезжать на местную сторону. На схеме существования эта часть соответствует шагам 2 и 2'。

Сохраните RawHandle в постоянном хранилище (локально)

Давайте переключим приезжатьплагин на родную сторону и посмотрим, как он себя поведет registerCallbackDispatcher api

Приведенный выше пример кода разделен на две части:

  1. В первой части существования мы рассматривали вопрос проживания. MyPlugin.kt файл, использовать Kotlin Пишу из родного плагина. Наш ответ на API «registerCallbackDispatcher» интересно, это от Dart завершить вызовиз,существовать Нет. 18 ОК, передано как параметр dispatcherHandle。существовать Нет. 21 Ладно, Воля, это спасает существование одно SharedPreference в постоянном хранилище.
  2. Часть 2. Только вспомогательный класс.,用于держатьичитатьSharedPreferencesсерединаизданные。

Это объяснение относится к отметке 2 дюйма на нашей диаграмме.

Запустите движок Dart в фоновом режиме.

Это основная часть истории, которую мы хотим движок Dart в фоновом режиме.и ВМ, но не запускать основную изоляцию и UI часть. Как показано на картинке 3 Как показано на рисунке, там написано «из есть За». кулисами Инициализатор процесса. Для простоты я выбрал BootComplete BroadcastReceiver,существоватьсброс настроек мобильного телефоназапускатьчасзапускать Dart VM, но в зависимости от требований вашего приложения вы можете решить, когда запускать Dart VM Правильное время:

существоватьвышеизкодсередина,Давайте посмотрим на типичный BroadcastReceiver в условиях проживания., который вызывается, когда существующий телефон завершает запуск. от onReceive , запускаем и звоним нашему из dart Диспетчер обратного вызова, разделенный на два основных этапа (из на картинке 4 и 5)。

  1. initializeFlutterEngine method:
  • Создайте объект FlutterLoader и проверьте, был ли он инициализирован.
  • существовать Нет. 19-20 строка запускается и ожидает завершения инициализации
  • ПолучатьприложениеизBundlePath,то есть корневой путь приложения
  1. executeDartCallback:
  • существовать Нет. 30 создание строки FlutterEngine объект
  • Следующийсуществовать Нет. 31 ОК, поймай нас, прежде чем существовать SharedPreferences серединадержатьиз**callbackDispatcher**ручка。检查ручкада否有效,Затемиспользовать RawHandle 作为参数ПолучатьCallbackInfo(Нет. 34 ХОРОШО)
  • 一旦нас有ПонятноcallbackInfo,нас就использовать DartEngine.dartExecutor существовать Dart завершить вызов callbackDispatcher Функция обратного звонка! из № на картинке 5 часть.

Эта Воля прямо из местного кодекса существует За кулисамивызов Dart сторонаизcallbackDispatcher

Суммируя,После перезагрузки телефона запустить,это Волясуществовать За кулисамизапускать Dart двигатель.

нравиться Как упоминалось ранее,callbackDispatcherтолько Похоже на: Функция main() — вспомогательная запись. Однажды запустить, Дарт API Сторонний плагин будет доступен, чтобы мы могли существовать За кулисами запускают любые изолированно Dart Логический или взаимодействует с другим плагином, пока UI Некоторые стоят на месте!

примернравиться,Мы сами изплагин можем предоставить EventChannel, обеспечивает поток событий для любого события, которое мы выбираем, этот поток событий может существовать. callbackDispatcher находился под наблюдением и существует Dart Получите события из конечного фона.

Нужно объяснить из-за чего,Следующие разделы не имеют отношения к изложенной выше теории изоляции фона.,Это всего лишь обычная функция изплагин,поставлять Dart API Для отправки и получения сообщений с локальной стороны.

Единственное отличие состоит в том, что как только он будет вызван, мы сможем взаимодействовать с ним из планировщика обратных вызовов.

Давайте посмотрим на код, а затем я его объясню.

Приведенный выше код разделен на три части:

  1. Первая часть - плагин API, существующий код, наконец, обеспечивает API прослушивать EventChannel Доставка сообщений и многое другое API, пример нравитьсязапускающего монитора зарядного устройства устройства и состояния аккумулятора. Эти события Воля проходят EventChannel Отправьте его обратно.
  2. Вторая часть — это локальная сторона вилки, существующая. 14 и 15 ОК, создадим специальный класс из StreamHandler。
  3. окончательно PluginEventEmitter Класс, это сообщение Воля, которое надо отправить приезжать. Dart Конец категории.

существовать PluginEventEmitter Класс наконец, определен запечатанный класс для отправки приезжать dart изсобытие, существование В этом примере есть два события: BootComplete и BatteryLevelStatus

PluginEventEmitter Также кэширует событие, прямо приехать dart сторонасуществовать EventChannel За этим ведется мониторинг.

взглянинравитьсячтосуществовать callbackDispatcher Используйте его в:

существующий планировщик обратных вызовов (вызывается из локального состояния после завершения существованиязаживающего),Мы сейчас существуемзарегистрируйтесь изплагинсобытие,ЗатемвызовstartPowerChangesListenerисуществовать侦听器середина捕获событие。

Итак, когда мы перезагружаем телефон, callbackDispatcher Воля называется и все эти Волясуществовать За кулисами бегите! Пока процесс активен (это тема другой статьи из..), событие Воля продолжает существовать За кулисами передано слушателю!

Пример исходного кода проекта

пожалуйста, направьте меняизgithubначальствоиз示пример项目,Он содержит полный исходный код!

У этого метода есть свои недостатки, он требует открытия приложения хотя бы один раз для регистрации функции обратного вызова callbackRawHandle.

Я должен сказать,существовать开始час,Я до сих пор считаю этот способ не самым простым для понимания и реализации.,Я надеюсь, что будущее будет существовать,Flutter Команда способна найти более простые решения.


Потрясающе! Поощряйте себя до конца приезжать. Надеюсь, я принёс некоторую пользу вашему вложению времени.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose