Flutter Web初尝试以及一些问题解决

3,408 阅读4分钟

Flutter 2在3月份发布以后,开放了移动端、Web端、桌面端的发布能力,之前一直使用Flutter开发移动应用,没有敢用Flutter做Web项目,近期有时间自己调研了一下,也遇到了一些问题,在这里记录一下。 创建一个Flutter项目做Demo,集成了一些插件:项目地址

目前遇到的问题(不断更新中...)

1、跨域
2、多设备调试
3、标题(Title)
4、获取应用版本号

一、跨域问题

主要使用了cached_network_image来加载网络上的图片来展现跨域问题,直接用Image.network也是可以的,在网络上随便找了一张图片via.placeholder.com/350x150

PS: 一般看一个插件支持那些平台,可以在pub.dev上看下面列出的平台,但是cached_network_image很奇怪,显示并不支持web,但是当浏览器运行起来后,也是可以加载出图片的。 image.png

1、本人习惯用VSCode开发,VSCode运行Flutter Web项目首先选择设备为Chrome Chrome

2、然后选择Debug,点击三角符号运行 调试项目

3、不出意外,运行成功后,Chrome就展现出项目了,这里首页用了一个第三方框架:gesture_password_widget,因为也想看看这个手势密码在Web上的表现 首页

4、根据上面的提示滑动正确的手势顺序,就进入了功能列表页面 功能列表页

5、点击Cached Network Image Demo,进入测试加载图片页面,发现图片加载失败,并且控制台报错了 加载失败

6、很明显,这边请求的图片服务器和页面运行的地址不通,产生了跨域问题 报错信息

7、解决方法在这篇文章里说的很详细:Flutter Web 跨域问题解决方案,里面推荐了多种方法,我这边用了第三种,类似启动一个代理服务的方式,在Demo项目里的lib/server/cors.dart文件中配置目标服务器地址和代理地址及端口,然后通过终端运行该文件,启动一个代理服务。

dart xxx/xxx/xxx/cors.dart

启动成功

8、这里我配的代理服务是localhost:4040,现在打开localhost:4040/350x150,图片加载成功 显示成功

9、然后把Demo项目里加载图片的地址改一下

// imageUrl: "http://via.placeholder.com/350x150",
imageUrl: "http://localhost:4040/350x150",

10、可以看到,图片已经可以加载出来了 加载成功

补充:后来看到了这篇文章,调试的时候也可以通过这种方式绕过跨域问题。

二、调试问题

接着上面,跨域问题解决后,我想在手机上通过浏览器测一下,目前项目启动在电脑上的地址是http://localhost:52754/#/,确认电脑和手机处于同一个网段后,我打开手机Safari浏览器,然后将地址的localhost修改为电脑的ip,发现居然无法打开 无法链接

尝试了不同的启动方式,如

flutter run -d chrome

也不起作用

在网上搜索的时候发现有人咨询过类似问题:flutter - 从真实的移动浏览器访问flutter localhost,里面的回答解释了为什么Flutter运行的Web项目不能充当服务器被访问,然后也给出了解决方法,大致意思就是让你先编译出来Web项目,然后在本地部署一下,就可以通过其他设备访问了。

这个方法虽然可以解决,但是不方便一边开发一边调试,于是再找解决方案,发现有人提供了这样一条命令

flutter run -d chrome --web-hostname xxx.xxx.xxx.xxx --web-port xxxx

尝试了一下,通过终端将电脑的ip地址输进去,再加个端口号,运行起来后,发现可以通过外部设备访问了 访问成功

接着我们修改一下代码内容,发现页面没有自动刷新,在控制台中看到如下提示,意思是改动过后,需要在终端输入命令r来刷新 提示

PS:这样会有一个新问题,就是上面跨域问题的配置,需要将localhost换成相同的ip地址,这样才能在外部设备也访问到配置的外部服务器地址

三、标题(Title)

网页标签上的标题,可以通过最外层的MaterialApp设置title

MaterialApp(
  title: '标题aaa'
  ...
)

网页标题 但是这样有个问题,不论页面怎么切换,永远都是显示这个标题,正常开发思维,肯定是切换到登录页,标题就显示‘登录’,设置页就显示‘设置’等等。

这边有两种解决办法:

1、直接在页面最外面包一层Title

@override
Widget build(Context context) {
  return Title(
    label: '当前页面的标题',
    primaryColor: Theme.of(context).primaryColor,
    child: ..,
  );
}

2、使用SystemChrome.setApplicationSwitcherDescription

@override
Widget build(BuildContext context) {
    SystemChrome.setApplicationSwitcherDescription(ApplicationSwitcherDescription(
      label: '当前页面的标题',
      primaryColor: Theme.of(context).primaryColor.value,
    ));


  return Container(...);
}

个人还是喜欢用第二种,第一种需要再嵌套一层的感觉不是很爽。。

四、获取应用版本号

以前开发App的时候,直接用package_info插件就可以获取版本号、包名等信息,但是看到package_info这个插件是不支持Web的,于是我就换了另一个package_info_plus,这个支持Web。

未完待续...