Фоновые задачи 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
Учебное пособие по Jetpack Compose для начинающих, базовые элементы управления и макет
boy illustration
Код js веб-страницы, фон частицы, код спецэффектов
boy illustration
【новый! Суперподробное】Полное руководство по свойствам компонентов Figma.
boy illustration
🎉Обязательно к прочтению новичкам: полное руководство по написанию мини-программ WeChat с использованием программного обеспечения Cursor.
boy illustration
[Забавный проект Docker] VoceChat — еще одно приложение для мгновенного чата (IM)! Может быть встроен в любую веб-страницу!
boy illustration
Как реализовать переход по странице в HTML (html переходит на указанную страницу)
boy illustration
Как решить проблему зависания и низкой скорости при установке зависимостей с помощью npm. Существуют ли доступные источники npm, которые могут решить эту проблему?
boy illustration
Серия From Zero to Fun: Uni-App WeChat Payment Practice WeChat авторизует вход в систему и украшает страницу заказа, создает интерфейс заказа и инициирует запрос заказа
boy illustration
Серия uni-app: uni.navigateЧтобы передать скачок значения
boy illustration
Апплет WeChat настраивает верхнюю панель навигации и адаптируется к различным моделям.
boy illustration
JS-время конвертации
boy illustration
Обеспечьте бесперебойную работу ChromeDriver 125: советы по решению проблемы chromedriver.exe не найдены
boy illustration
Поле комментария, щелчок мышью, специальные эффекты, js-код
boy illustration
Объект массива перемещения объекта JS
boy illustration
Как открыть разрешение на позиционирование апплета WeChat_Как использовать WeChat для определения местонахождения друзей
boy illustration
Я даю вам два набора из 18 простых в использовании фонов холста Power BI, так что вам больше не придется возиться с цветами!
boy illustration
Получить текущее время в js_Как динамически отображать дату и время в js
boy illustration
Вам необходимо изучить сочетания клавиш vsCode для форматирования и организации кода, чтобы вам больше не приходилось настраивать формат вручную.
boy illustration
У ChatGPT большое обновление. Всего за 45 минут пресс-конференция показывает, что OpenAI сделал еще один шаг вперед.
boy illustration
Copilot облачной разработки — упрощение разработки
boy illustration
Микросборка xChatGPT с низким кодом, создание апплета чат-бота с искусственным интеллектом за пять шагов
boy illustration
CUDA Out of Memory: идеальное решение проблемы нехватки памяти CUDA
boy illustration
Анализ кластеризации отдельных ячеек, который должен освоить каждый&MarkerгенетическийВизуализация
boy illustration
vLLM: мощный инструмент для ускорения вывода ИИ
boy illustration
CodeGeeX: мощный инструмент генерации кода искусственного интеллекта, который можно использовать бесплатно в дополнение к второму пилоту.
boy illustration
Машинное обучение Реальный бой LightGBM + настройка параметров случайного поиска: точность 96,67%
boy illustration
Бесшовная интеграция, мгновенный интеллект [1]: платформа больших моделей Dify-LLM, интеграция без кодирования и встраивание в сторонние системы, более 42 тысяч звезд, чтобы стать свидетелями эксклюзивных интеллектуальных решений.
boy illustration
LM Studio для создания локальных больших моделей
boy illustration
Как определить количество слоев и нейронов скрытых слоев нейронной сети?
boy illustration
[Отслеживание целей] Подробное объяснение ByteTrack и детали кода