Автор этой статьи:Тао Тао, несанкционированное воспроизведение запрещено.
задний план
С момента своего появления Flutter стал лидером в области кросс-энд разработки.Все больше и больше компаний в стране и за рубежом встали на путь исследования флаттера.Наша клиентская команда Zhiyun пытается разработать небольшое количество флаттера с 2018 года. ., после года технических исследований и осадков, в 2019 г. группа по работе с клиентами инициировала полную флаттеризацию приложения Zhiyun Health (на основе флаттерного SDK 1.9.0). Флаттер-версия стабильно работает онлайн.
В этой статье описываются проблемы, с которыми мы столкнулись в полном приложении флаттера, и объясняется, как мы их решили.
Проблемы с использованием Flutter WebView
Введение
Поскольку флаттер преобразует дерево виджетов в текстуру, а затем реализует отрисовку элементов управления через Skia, в принципе определено, что пользовательский интерфейс флаттера не может напрямую использовать собственные элементы управления Android/IOS, а также не может использовать собственные зрелые и стабильные WebView, MapView и т. д. Для этой ситуации у нас есть два решения:
-
Разработайте плагин, откройте Activity/Controller в плагине, загрузите и отобразите собственный WebView через Activity/Controller, это решение может полностью повторно использовать все возможности собственного WebView, а также может сильно настраивать WebView в соответствии с требованиями, но есть серьезная проблема.Недостаток в том, что невозможно открыть флаттер-страницу из открытого нативного WebView, а потом переоткрыть флаттер-страницу и прикрыть ее под нативным WebView.Я полагаю, что мелкие партнеры, использующие это решение, сталкивались Эта проблема. (Например, flutter_webview_plugin использует эту схему)
-
До flutter sdk 1.20 была официально предоставлена вещь под названием PlatformView.Сторона Android называлась AndroidView, а сторона IOS называлась UIKitView.С помощью этих двух виджетов разработчики могли встраивать собственные компоненты Android/IOS в дерево виджетов Flutter. (официальный webview_flutter реализован таким образом)
Выберите решение Flutter WebView в зависимости от бизнес-сценария
-
Первое решение подходит только для открытия новой страницы, чтобы открыть веб-просмотр, и веб-просмотру не нужно снова открывать флаттер-страницу.Преимущество этого решения заключается в том, что оно может избежать всех ям, с которыми флаттер столкнется при использовании собственных элементов управления. .
-
Второе решение — это официальная практика для флаттера использовать собственные элементы управления через PlatformView.До flutter sdk 1.22 он был только в состоянии предварительного просмотра, не рекомендуется для производства, и есть много оставшихся проблем.
Возвращаясь к нашему конкретному бизнес-сценарию, в главном интерфейсе приложения Zhiyun Health есть четыре вкладки, среди которых сообщество и торговый центр — это страницы h5, которые необходимо загрузить с помощью веб-просмотра.Один из процессов выглядит следующим образом: домашняя страница торгового центра -> страница покупки продукта -> страница чата обслуживания клиентов, а страница чата обслуживания клиентов — это страница, разработанная флаттером. Первое решение явно не может удовлетворить наши потребности, поэтому мы используем официальное решение webview_flutter.
Выбор официальной предварительной версии webview_flutter имеет много проблем, которые необходимо решить в срочном порядке, поэтому мы начали долгий путь, чтобы управлять проблемами веб-просмотра флаттера. . .
Официальный анализ принципа webview_flutter
-
AndroidView (Android):
Способ: До версии flutter sdk 1.20 флаттер отрисовывал содержимое, которое нужно отрисовать, в память VirtualDisplay через AndroidView, а затем получал данные отрисовки и отрисовывал их в Surface через соответствующий textureId. VirtualDisplay похож на виртуальную область отображения, выводит текстуры через VirtualDisplay, а сторона Android может напрямую добавлять собственные элементы управления в иерархию дерева виджетов Flutter.
дефект:
-
Поскольку AndroidView отображается в памяти VirtualDisplay, когда пользователь щелкает, чтобы увидетьAndroidViewКогда фактический щелчок представляет собой визуализированную текстуру Flutter (текстуру), событие касания пользователя отправляется во Flutter View, а неAndroidView, поэтому AndroidView, реализованный таким образом, требует специальной обработки событий касания, а проблема, вызванная специальной обработкой, заключается в том, что информация о касании отправляется неправильно или теряется.
-
Поскольку местоположение VirtualDisplay всегда не находится в фокусе, а сфокусированное окно во Flutter обычно представляет собой текстуру Flutter и виджет, которые фактически удерживаются и видны пользователю, поэтому этот метод требует специальной обработки проблем с фокусом.
-
Из-за первых двух дефектов AndroidView очень хрупок в обработке касаний и фокуса, а использование WebView добавлено в AndroidView, т.к. Android WebView имеет собственную внутреннюю логику для создания и установки входных соединений, что усложняет первые две проблемы Теперь возникают всякие странные проблемы, ненормально всплывает виртуальная клавиатура, копируется текст, недоступен диалог обмена и т. д.
-
-
UIKitView (IOS):
Способ: На стороне iOS метод реализации отличается от того, что на стороне Android. Используется метод смешивания слоя: трепетание имеет два прозрачных текстура: один под собственным видом на iOS и один над внешним видом на iOS, который необходимо отобразить В родном представлении iOS ниже прозрачной текстуры ниже нарисован на прозрачной текстуре, и на прозрачной структуре выше. Наконец, все слои в сочетании, чтобы получить интерфейс Нужно. Таким образом, сторона iOS также можно добавить нативные элементы управления непосредственно на иерархию дерева виджета флаттера.
Преимущество: Используются все комбинации текстур, и они по-прежнему находятся в рамках логики рендеринга флаттер-виджета.Нет проблемы, требующей специальной обработки на стороне Android.
Так почему же сторона Android не использует этот метод?
Причина в том, что после рендеринга кадра на iOS в системе появится callback-уведомление, например:Когда представление iOS перемещается вниз
1px
, мы также можем уменьшить все остальные элементы управления Flutter в его списке.1px
.Однако в системе Android нет системного API для рендеринга обратных вызовов, и синхронный рендеринг вывода невозможен.
-
Гибридная композиция (Android):
Способ: С flutter sdk 1.20 официально запущен новый режим Hybird Composition аналогичный IOS PlatformView.В этом режиме официально добавлен FlutterImageView.Сам FlutterImageView является обычным нативным View,у которого есть возможность смешивать слои. PlatformView реализует смешивание слоев, добавляя собственные элементы управления во FlutterView, а затем используя FlutterImageView.
Улучшать: Подобно реализации комбинации уровней IOS, нет необходимости в специальной обработке, такой как VirtualDisplay, которая может решить предыдущие сенсорные функции, программную клавиатуру и текстовые функции.
Проблемы с официальным webview_flutter
Когда IOS WebView прокручивается, он зависает
Феномен: Перед версией 0.0.7 webview_flutter, на стороне IOS, используйте webview_flutter для загрузки страницы h5 с помощью WebView и много раз перемещайте ее, страница зависает.issues
Решение на тот момент:
- Разветвите исходный код webview_flutter, добавьте таймер на стороне IOS, подключайтесь и активируйте жест каждые несколько секунд.
Рекомендуемые решения:
- Обновите webview_flutter до 1.0.7 и flutter sdk до 1.22.3, чтобы решить проблему.
Проблема, заключающаяся в том, что программная клавиатура Android WebView ненормально появляется, а копируемый текст недоступен.
Феномен:
До версии 1.0.0 webview_flutter на стороне Android используйте webview_flutter, чтобы использовать WebView для загрузки страницы h5, щелкните поле ввода на странице h5, программная клавиатура не будет всплывать и не может быть свернута, а длинная нажатие контроля доступа к тексту на странице h5 будет недоступно.. вопрос.
Решение на тот момент:
- До flutter sdk1.20 эта проблема официально не фиксировалась, мы модифицировали логику InputConnection через код форка webview_flutter, что временно решило эту проблему, но некоторые текстовые функции до сих пор не решены.
- Исходя из этого, мы сделали еще одну вещь, рефакторинг всех h5-страниц вкладки основного интерфейса с флаттером, а на домашней странице уже нет h5-страниц, что временно позволило избежать некоторых неразрешимых проблем webview_flutter.
- Начиная с версии flutter sdk1.20 официально реализована гибридная схема композиции, изменив исходный код webview_flutter, мы сделали ее гибридной композиционной схемой и решили проблему всплывающего окна программной клавиатуры WebView на стороне Android и недоступность текстовой функции.
Рекомендуемые решения:
- Если вы используете версию до webview_flutter 1.0.0, рекомендуется обновить flutter sdk до 1.20, а затем изменить официальный исходный код webview_flutter для поддержки схемы гибридной композиции.Однако при использовании этого решения возникнет проблема, заключающаяся в том, что переключение фона, а затем повторный вход в приложение будут мигать. Ниже я объясню, как решить эту проблему..
- Если вы используете webview_flutter версии 1.0.3, обновите flutter SDK до 1.22.3, чтобы решить эту проблему.
Когда Android WebView переключается в режим Hybird Composition, откройте страницу WebView, переключите приложение в фоновый режим, а затем снова войдите в приложение, проблема вернется.
Феномен:
Если вы используете версию до webview_flutter 1.0.0, а затем модифицируете официальный исходный код webview_flutter для поддержки схемы гибридной композиции, а flutter sdk равен 1.20, вы обнаружите, что страница WebView открывается на стороне Android, а приложение переключается в фоновый режим, а затем снова входит в приложение, что приведет к сбою приложения.issues
Решение на тот момент:
- Чиновник начал использовать две ссылки для хранения объекта изображения в Flutterimage, что привело к потере ссылки при выпуске изображения, и в конечном итоге изображение так и не было выпущено должным образом.Затем чиновник добавил список для хранения различных объектов изображения. , При перемещении по списку он гарантирует, что все изображения, которые существуют в истории, правильно выпущены.
- Преждевременное удаление представления поверхности из дерева представления вызывает запуск PlatformView::NotifyDestroyed()->Shell::OnPlatformViewDestroyed(). На основании предыдущей проблемы кадр, хранящийся в изображении, не может быть должным образом освобожден, когда приложение находится в фоновом режиме и обновляется. к новому кадру и, наконец, вызвать перегрузку очереди кадров, чтобы вызвать сбой исключения на уровне Java.
- согласно сОфициальная программа, После изменения исходного кода FlutterImageView мы перекомпилируем движок флаттера и используем скомпилированный продукт для упаковки приложения, проблема действительно решена.
Рекомендуемые решения:
- Обновление flutter sdk до 1.22.3 решило проблему.
Когда Android WebView переключается в режим Hybird Composition, WebView не будет повторно использоваться при повторном открытии страницы WebView.
Феномен:
После использования схемы гибридной композиции, хотя многие проблемы во взаимодействии решены, есть утечка памяти.Наиболее очевидным проявлением является то, что когда мы повторно открываем страницу веб-просмотра, если мы используем chrome://inspect для просмотра загрузки webview, будет проблема.Многие webviews не перерабатываются.issues
Решение на тот момент:
- от официальногоissuesНашел решение, но ни одна официальная не слилась только в 1.22.
- Согласно официальному решению, мы влили изменения во флаттер-движок нашего локального форка, перекомпилировали флаттер-движок и использовали скомпилированный продукт для упаковки приложения — проблема действительно решена.
Рекомендуемые решения:
- Обновление flutter sdk до 1.22.3 решило проблему.
Когда Android WebView переключается в режим Hybird Composition, страница WebView постоянно открывается, и возникает проблема с утечкой памяти.
Феномен:
После использования схемы гибридной композиции, в дополнение к официальным ошибкам, из-за плохого понимания принципа смешивания слоев гибридной композиции, мы добавили LinearProgressIndicator в виджет WebView, чтобы заполнить пустое время загрузки WebView h5, что также вызвал утечку памяти при смешивании слоев FlutterImageView.
Решение на тот момент:
- Во время презентации LinearProgressIndicator сделайте скриншот веб-представления Placeholder.
Рекомендуемые решения:
- Обновление flutter sdk до 1.22.3 решило проблему.
webview_flutter 1.0.7 открывает веб-просмотр, затем закрывает страницу веб-просмотра, экран телефона поворачивается, и приложение аварийно завершает работу.
Феномен:
После обновления webview_flutter до 1.0.7, до flutter sdk1.22.1, откройте страницу веб-просмотра, затем выйдите на предыдущую страницу, затем поверните экран телефона, и приложение вылетит.issues
Решение на тот момент:
- от официальногоissuesНашел решение, но ни одна официальная не слилась только в 1.22.
- Согласно официальному решению, мы влили изменения во флаттер-движок нашего локального форка, перекомпилировали флаттер-движок и использовали скомпилированный продукт для упаковки приложения — проблема действительно решена.
Рекомендуемые решения:
-
Обновление flutter sdk до 1.22.3 решило проблему.
Суммировать
Выше перечислены все проблемы, с которыми мы столкнулись при использовании нативного веб-просмотра во флаттере.От flutter sdk1.9 до 1.22.3 мы отследили и решили все проблемы с использованием флаттерного веб-просмотра. Будь то анализ исходного кода для временного решения или поиск официального решения из официальных проблем, мы прошли все ямы до сих пор, флаттер sdk1.22.3 и, наконец, открыли хорошие новости.После проверки все ямы, с которыми мы столкнулись ранее, в настоящее время являются официальными.Все они были решены, и мы также планируем вернуть ранее настроенный движок в официальную стабильную ветку!