扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
在此之前先推荐看大佬的: 填坑指导
创新互联主营荆州网站建设的网络公司,主营网站建设方案,手机APP定制开发,荆州h5成都微信小程序搭建,荆州网站营销推广欢迎荆州等地区企业咨询
iOS需要注意:
1、flutter2.0要求cocoapods 升级到1.9.0
详情看这篇博客
2、原来flutter项目中的podfile文件是旧版本的ccocoapods了,删除podfile和对应的.lock,然后flutter项目重新运行使用它自动生成的podfile文件
3、安装CocoaPods
卸载cocoapods:sudo gem uninstall cocoapods
查看cocoapods版本:pod --version
指定版本安装:
sudo gem install -n /usr/local/bin cocoapods -v 1.9.3(新MacOS系统升级)
不指定版本安装
sudo gem install -n /usr/local/bin cocoapods
说明 :老项目sdk1.17.0===升级到2.0.1,当前所有操作基于win平台
到此为止环境已经准备妥当,正式进入项目修改。
所有的插件都要适配到空安全,插件是否支持均会有对应说明Null safety,适配过程不确定版本的话,可以使用dio: any,适配完事后再在pubspec.lock文件中查看具体的版本修改过来,实在有部分插件没有支持的,参考下面
部分插件在适配空安全的版本放弃维护了,得自行更新或寻找替代,如: flutter_swiper 变为 flutter_swiper_null_safety ,插件更新后要注意项目中的用法是否需要更新
2.1.1: 以前采用的是 provide 插件共享全局数据,现在变化为 provider ,用法改变, 点击参考 ,以防文章丢失,我重复一遍:
比如:
2.1.2: dio版本升级到4.0.0最新版后,部分用法改变
2.2.1
2.2.2
解决方案:
2.2.3
解决方案:
2.2.4
解决方案:
2.2.5
解决方案:
2.2.6
解决方案:
2.2.7
解决方案:
2.2.8
解决方案: child 换为sliver
2.2.8.1
解决方案: 项目目录下: android--app-build.gradle --minSdkVersion改为:18 或者19
2.2.8.2
解决方案: 在pubspec.yarm管理里面添加:publish_to
2.2.8.3
解决方案: video_player升级后字段发生了变化,initialized字段更换为:isInitialized(_controller.value.isInitialized)
2.2.8.4
解决方案:
2.2.8.5
解决方案:
2.2.8.6
解决方案: 方案一:删除ios目录下的Podfile.lock 文件然后重新运行 pod install命令
方案二:删除ios目录下的Podfile.lock与Podfile文件 重新运行flutter run或flutter build ios
方案三:删除ios目录,重新运行 flutter create . 命令,注意有"."这个符号不要忘记
2.2.8.7
这个报错一般对应的就是下面的报错,注意看后面的报错信息,看是哪个插件报错。
解决方案: 把Podfile的版本注释打开,改为platform :ios, '9.0' 或者是更高的版本
全局替换
1.将new List() 替换为[];
2.TextField的inputFormatters:[WhitelistingTextInputFormatter.digitsOnly] 替换为[FilteringTextInputFormatter.digitsOnly]
3.TextField的inputFormatters:[WhitelistingTextInputFormatter(RegExp("[a-z|A-Z|0-9]"))]替换为FilteringTextInputFormatter.allow(RegExp("[a-z|A-Z|0-9]"))
4.Stack组件中overflow: Overflow.visible改为 clipBehavior: Clip.none;overflow: Overflow.clip改为clipBehavior:Clip.hardEdge
5.ListWheelScrollView组件中clipToSize = false改为clipBehavior: Clip.none,clipToSize = true改为 Clip.hardEdge
6.TextField中maxLengthEnforced: true改为maxLengthEnforcement:MaxLengthEnforcement.enforced
7.FlatButton、RaisedButton、OutlineButton的变化: 官方参考
颜色的属性发生了变化,由原来的Color 变为了MaterialStatePropertyColor, 这是未了解决不同状态(pressed、hovered、focused、disabled)下按钮颜色的变化
例如
8.出现如下警告
9.showSnackBar报错误
解决方案: Scaffold换为ScaffoldMessenger
10.textSelectionColor弃用
解决方案:
11.charts_flutter升级后属性报错
解决方案:
12.flutter 真机调试无法访问网络,dio报错
解决方案:
android:
ios:
问题12完整参考
Flutter Dio源码分析(一)--Dio介绍
Flutter Dio源码分析(二)--HttpClient、Http、Dio对比
Flutter Dio源码分析(三)--深度剖析
Flutter Dio源码分析(四)--封装
Flutter Dio源码分析(一)--Dio介绍视频教程
Flutter Dio源码分析(二)--HttpClient、Http、Dio对比视频教程
Flutter Dio源码分析(三)--深度剖析视频教程
Flutter Dio源码分析(四)--封装视频教程
github仓库地址
本文会手把手教你该怎么去封装一个类库,平时在我们的工作中都是拿着别人的造好的轮子在使用,这篇文章将带你怎么去自己造轮子,以后再碰到别的类库需要对其进行封装的时候提供一个的思路和方法。
在前面的文章中,我们对 Dio 的基本使用、请求库对比、源码分析,我们知道 Dio 的使用非常的简单,那为什么还需要进行封装呢?有两点如下:
当组件库方法发生重要改变需要迁移的时候如果有多处地方用到,那么需要对使用到的每个文件都进行修改,非常的繁琐而且很容易出问题。
当不需要 Dio 库的时候,我们可以随时方便切换到别的网络请求库,当然 Dio 目前内置支持使用第三方库的适配器。
因为一个应用程序基本都是统一的配置方式,所以我们可以针对 拦截器 、 转换器 、 缓存 、 统一处理错误 、 代理配置 、 证书校验 等多个配置进行统一管理。
因为我们的应用程序在每个页面中都会用到网络请求,那么如果我们每次请求的时候都去实例化一个 Dio ,无非是增加了系统不必要的开销,而使用单例模式对象一旦创建每次访问都是同一个对象,不需要再次实例化该类的对象。
这是通过静态变量的私有构造器来创建的单例模式
我们对 超时时间 、 响应时间 、 BaseUrl 进行统一设置
因为不管是 get() 还是 post() 请求, Dio 内部最终都会调用 request 方法,只是传入的 method 不一样,所以我们这里定义一个枚举类型在一个方法中进行处理
我们已经把 Restful API 风格简化成了一个方法,通过 DioMethod 来标明不同的请求方式。在我们平时开发的过程中,需要在请求前、响应前、错误时对某一些接口做特殊的处理,那我们就需要用到拦截器。 Dio 为我们提供了自定义拦截器功能,很容易轻松的实现对请求、响应、错误时进行拦截
我们发现虽然 Dio 框架已经封装了一个 DioError 类库,但如果需要对返回的错误进行统一弹窗处理或者路由跳转等就只能自定义了
在我们发送请求的时候会碰到几种情况,比如需要对非open开头的接口自动加上一些特定的参数,获取需要在请求头增加统一的 token
在我们请求接口前可以对响应数据进行一些基础的处理,比如对响应的结果进行自定义封装,还可以针对单独的 url 做特殊处理等。
我们看了转换器的介绍,发现和拦截器的功能差不多,那为什么还要存在转换器,有两点:
执行流程: 请求拦截器 请求转换器 发起请求 响应转换器 响应拦截器 最终结果 。
只会被用于 'PUT'、 'POST'、 'PATCH'方法,因为只有这些方法才可以携带请求体(request body)
会被用于所有请求方法的返回数据。
在开发过程中,客户端和服务器打交道的时候,往往会用一个 token 来做校验,因为每个公司处理刷新token的逻辑都不一样,我这里举一个简单的例子
为什么我们需要有取消请求的功能,如果当我们的页面在发送请求时,用户主动退出当前界面或者app应用程序退出的时候数据还没有响应,那我们就需要取消该网络请求,防止不必要的错误。
由 服务器生成 的 一小段文本信息 ,发送给浏览器,浏览器把 cookie 以kv形式保存到本地 某个目录下的文本文件内,下一次请求同一网站时会把该 cookie 发送给服务器。
cookie 的使用需要用到两个第三方组件 dio_cookie_manager 和 cookie_jar
因为在我们平时的开发过程中,会碰到一种情况,在进行网络请求时,我们希望能正常访问到上次的数据,对于用户的体验比较好,而不是展示一个空白的页面,该缓存主要是 《Flutter实战》网络接口缓存 提供参考。
我们在程序退出后内存缓存将会消失,所以我们用 shared_preferences 进行磁盘缓存数据。
在我们用flutter进行抓包的时候需要配置 Dio 代理。由 DefaultHttpClientAdapter 提供了一个 onHttpClientCreate 回调来设置底层 HttpClient 的代理。
用于验证正在访问的网站是否真实。提供安全性,因为证书和域名绑定,并且由根证书机构签名确认。
日志打印主要是帮助我们开发时进行辅助排错
最近在做公司工业互联网的一个项目 之前做了一个ipad 版本的 在使用dio网络请求框架的时候发现请求登录的时候后台一直报签名错误问题 检查了几遍写的签名方法没有发现错误 后面仔细查了下 是服务器不能识别我传的数据。。。
如果content-type是form-data 我们需要通过FormData类来构建数据,否则服务器将无法识别
同时需要传入一个Option指明content-type,而form-data的content-type完整类型表述为:multipart/form-data
主要我是个新手啊
查看源码
headers里面并有multipart/form-data 这个类型啊 讲道理这个是常用的contentType啊 应该要列出来才对啊
咋整?
自己设置。。。。
后台就可以正常接收表单参数了
下面这种情况下,为 InkWell 设置的 splashColor 不会生效:
需要用 Material 去除背景色,然后将颜色设置在 InkWell 外部:
在 Dialog builder 中使用 WillPopScope 禁用返回键返回:
注意:使用此方法同时也会禁用 iOS 上的手势滑动返回功能,推荐判断平台后再使用。
修改对话框中的复选框状态,最简便的方法是通过 Element 中的 markNeedsBuild 方法:
当然,更推荐的做法是通过 StatefulBuilder ,然后就可以在 Dialog 中调用 setState 方法了,不过在调用 setState 时需要判断 Dialog 是否已经关闭,否则会造成 setState() called after dispose() 的错误,可以通过添加一个标志位来解决,如下:
在 Web 中加载网络图片有时会失败,遇到这样的报错: Exception caught by image resource service... ,造成该错误的原因通常是,图片跨域了(见 跨域资源共享 )。最简单的解决办法是, 使用 HTML 渲染加载 ,而不是默认的 CanvasKit。
Flutter 中所有的 list 默认都是没有 ScrollBar 的,必须使用 ScrollBar 组件。ScrollBar 组件通过监听 ScrollView 的 ScrollNotification 来刷新位置,所以 List 的长度必须是固定的。
当使用 WebView 等高度不定的组件时会出现内容被截断的情况,通常可以使用 NestedScrollView 来解决该问题,需要在 WebView 外部嵌套 SingleChildScrollView。
虽然使用了缓存,而且也是用 builder 加载图片的,但是发现一个现象:滑动屏幕后图片短暂消失并重新加载了。图片高度很高时这种现象更加明显,其原因是超出屏幕范围一定距离的组件被重新渲染了。解决方法是在 ListView 上设置 cacheExtent 参数:
该参数的作用是改变超出屏幕高度后继续渲染的范围(以像素为单位),比如设置成 9999 后意味着超出屏幕 10000 像素以内的内容都会被保留下来。
借助 IntrinsicHeight 组件:
另外,IntrinsicHeight 还可以用于 Dialog 或者 BottomSheet 中,使得其中的元素 显示内在元素的高度 ,从而避免元素因为约束的存在而不显示或者高度太高(比如在使用了 Column 或者 Row 的时候)。
在通过 Uri 的 queryParameters 获取 query 参数时,发现有些链接会抛出下面异常:
造成该异常的原因是 Uri 默认使用 utf-8 解码超链接字符串,如果链接中包含非 utf-8 字符,就会造成上面的错误,相关 issue 见: issue #31621 。目前该 issue 处于 open 的状态,暂时的解决办法是,在所有使用到 queryParameter 的地方用 try..catch 捕捉可能抛出的异常。
Flutter 开发非常依赖各种官方或第三方的插件,而在使用这些插件时多少都会遇到一些问题,大部分问题都可以通过搜索和查找 issue 来解决。这里记录下一些我在使用部分插件时遇到的问题及其解决方法。
目前该库没有图片加载完成的回调(见 issue #545 ),不过我们可以通过在 imageBuilder 中来添加回调:
这是一个应用内更新插件,安卓 10 以上安装时需要在 manifest 中添加以下内容:
目前功能最强大的 WebView 插件,基本能满足绝大部分移动端网页加载的需求,而且可定制化程度高。
一般通过 CookieManager 修改 Cookie,拦截请求并修改请求对象的 Header 不会生效。
InAppWebViewOptions 的 userAgent 只在 iOS 上生效,而 applicationNameForUserAgent 只在 Android 上生效,所以最好的做法是分平台设置 InAppWebViewOptions ,而且需要注意,由于设置 userAgent 后会覆盖默认的 UserAgent,所以如果需要在默认的 UserAgent 上添加其它参数,iOS 上需要通过 InAppWebViewController.getDefaultUserAgent() 获取默认 UserAgent 参数,而 Android 不需要添加。
如果图片源或者请求是 http 的,为了在 Android 上正常加载请求,必须在 AndroidInAppWebViewOptions 中将 mixedContentMode 设置为 AndroidMixedContentMode.MIXED_CONTENT_ALWAYS_ALLOW 。
当我们想要设置全屏图片的时候,由于默认的 Constraint 会将图片居中显示,所以图片四周会留有空隙。为了去除这个限制,我们需要 Xcode 中打开 LaunchScreen.storyboard,然后在 View Controller 的 View 和 LaunchImage 上的 Safe Area 去掉。
具体设置方法:右侧 Inspector 面板 Show the Size inspector 解选 Layout Margins 中的 Safe Area Relative Margins,拖动图片占满全屏,然后根据 View Controller Scene 的 Warning,更新 Constraint 就可以了。
在集成某些三方库之后,在使用命令行运行 iOS 模拟器的时候可能会遇到下面这个报错:
这是因为 iOS 模拟器未来将会兼容 arm64 架构,但是目前还不支持,所以我们需要修改 Build Setting 使得能够在 x86_64 的模拟器上运行,操作步骤见 这里 。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流