У меня очень сложное приложение 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 .