Использование веб-просмотров во флаттере - PullRequest
2 голосов
/ 19 марта 2020

У меня очень сложное приложение Cordova на Android, которое я разрабатывал в течение года. Приложение использует один кастом, т.е. написанный мной плагин Cordova. Я считаю порт приложения iOS. Я планирую переключиться на Flutter, чтобы иметь только одну кодовую базу для поддержки - в противном случае весь плагин придется переписать для iOS.

* 1002. * С чистой HTML5 + ES6 + CSS3 это работает замечательно хорошо, и я не вижу причин, чтобы выбросить все это и начать все сначала как чистое приложение Flutter. Введите WebViews. Я планирую использовать весь мой текущий код Cordova Webview - по сути, весь проект Cordova www folder - в виде веб-приложения во флаттере. Ключом ко всему этому является возможность эффективной двусторонней связи между WebView и Flutter. Для этого я написал небольшой скелетный проект. Файл main.dart для этого проекта показан ниже
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:convert';
import 'package:webview_flutter/webview_flutter.dart';

void main() => runApp(Webby());

class Webby extends StatelessWidget 
{
 @override Widget build(BuildContext context) 
 {
  return MaterialApp
  (
   title: 'Flutter Demo',
   theme: ThemeData(primarySwatch: Colors.blue,),
   home: Feuille(),
  );
 }
}

class Feuille extends StatefulWidget
{
 Feuille({Key key}):super(key: key);
 @override  _FeuilleState createState() => _FeuilleState();
}

class _FeuilleState extends State<Feuille>
{
 WebViewController wVC; 
 @override Widget build(BuildContext context) 
 {
  SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]);  
  return Scaffold
  (
   body:SafeArea
   (
    child:Column
    (
     children:<Widget>
     [
      Expanded
      (
       child:Container
       (
        margin:const EdgeInsets.all(0.0),
        child:WebView
        (
         debuggingEnabled:true, 
         initialUrl:'',
         javascriptMode:JavascriptMode.unrestricted,
         onWebViewCreated:registerController,
         javascriptChannels:Set.from
         ([JavascriptChannel(name:'JSBridge',onMessageReceived:handleMessage)]),
        ),),)])));
 }

 Future<void> handleMessage(JavascriptMessage message) async
 {
  print(message.message);
  wVC.evaluateJavascript("addNums(10,21)");
 }

 void registerController (WebViewController controller) async
 {
  wVC = controller;
  String html = await rootBundle.loadString('assets/index.html');
  wVC.loadUrl(Uri.dataFromString(html,mimeType:'text/html',
  encoding:Encoding.getByName('utf-8')).toString());
 }
}

Локальный HTML, загруженный в это веб-представление, показан ниже

<!DOCTYPE html>
<html>
 <head>
  <meta name='viewport'
   content='user-scalable=no, initial-scale=1, maximum-scale=1, 
   minimum-scale=1, width=device-width, height=device-height' />
   <meta charset='utf-8' />
 </head>  
 <body>
  <p>The result is <span id="spnResult">Not Available Yet</span></p> 
 </body>
 <script>
   window.addEventListener("load",flutterReady);

   function flutterReady()
   {
    alert("Sending message");
    setTimeout(function(){JSBridge.postMessage("This is London calling");},5000);
   } 

   function addNums(n1,n2)
   {
    document.getElementById("spnResult").innerText = n1 + n2;
   }
  </script>
</html>

Наконец, файл pubspec.yaml для Проект выглядит следующим образом:

name: webby
description: Webby Project

version: 1.0.0+1

environment:
  sdk: ">=2.1.0 <3.0.0"

dependencies:
 flutter:
  sdk: flutter

 cupertino_icons: ^0.1.2
 path_provider: ^1.4.0
 permission_handler: ^3.3.0
 connectivity: ^0.4.5+6
 webview_flutter: ^0.3.19+9

dev_dependencies:
 flutter_test:
 sdk: flutter


flutter:
 uses-material-design: true
assets:
  - assets/

Теперь мои вопросы

  • Я использую этот каркасный проект, чтобы проверить, могу ли я общаться в двух направлениях: от Webview, размещенного JS до Flutter и от Flutter обратно к Webview размещены JS. Это работает - очень хорошо. Тем не менее, есть вещи, которые я сделал здесь довольно вслепую - это мой второй день с Flutter - который нуждается в разъяснении

  • Я использовал событие window.load в HTML5, чтобы знать, когда Я начинаю общаться с Флаттером. Это моя замена для события Cordova.docReady. Разумно ли предположить, что когда это событие произойдет, Flutter будет «готов», WebViewController будет доступен и c?

  • В моих усилиях заставить WebView занять весь На экране устройства я использовал Scaffold...SafeAera...Expanded... довольно просто, потому что столкнулся с тем, что он используется для показа полноэкранного изображения, и это сработало для меня. Тем не менее, мне не ясно, что это лучший / правильный способ делать вещи

  • Я отмечаю, что pubspec.yaml определяет использование Material Design и "Widget", являющийся здесь создан MaterialApp. Учитывая, что весь мой пользовательский интерфейс создается и управляется с помощью HTML5 + CSS3 + ES6 в WebView, не существует более простого способа создания виджета, который может повлечь за собой некоторые преимущества в производительности и памяти

  • Я встречал комментарии о том, что WebView работает медленно, плохо рендерится на iOS et c. По моему опыту, люди, которые делают такие комментарии, обычно склонны полагаться на «рамки», которые налагают ненужное бремя на систему. С чистой HTML + ES6, которая опирается только на HTML5 DOM, так как его производительность "framework" никогда не была проблемой для меня. Существует ли какая-либо известная причина, по которой Flutter WebView (который в конечном счете является WebView, поставляемым операционной системой) должен работать хуже?

  • И наконец: как только я получил это, мне нужно начать реализацию GeoLocation, Наблюдение за сетью Wi-Fi, мониторинг акселерометра, ввод-вывод, управляемый веб-сокетом, локальное хранилище файлов, хранилище базы данных SQLite et c. Соответствуют ли API, предоставляемые Fluter, этим задачам и соответствуют ли они операционной системе c, чтобы действительно генерировать приложения для Android и iOS?

Я был бы очень благодарен всем, кто мог бы дать здесь несколько советов и указаний.


Я не уверен, что когда-либо получу ответ здесь. Тем не менее, сноска для любого, кто работает в этой теме и пытается скопировать то, что я сделал до сих пор.

Проще говоря - это не будет работать. Использование Uri.dataFromString(... позволит вам показать документ stati c HTML со встроенными стилями и JS. Он не сможет получить доступ к таблицам стилей и сценариям, хранящимся в других файлах / папках внутри папки Flutter assets. Для этого вам нужно запустить локальный HTTP-сервер. Хотя вы можете попытаться раскрутить свою собственную, это не стоит делать. Попробуйте вместо этого использовать отличный и хорошо документированный плагин flutter_inappwebview .

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