当前位置: 首页 > news >正文

flutter遇到问题及解决方案

目录

1、easy_refresh相关问题

2、 父子作用域关联问题

3. 刘海屏底部安全距离

4. 了解保证金弹窗 iOS端闪退 (待优化)

5. loading无法消失

6. dialog蒙版问题

7. 倒计时优化

8. scrollController.offset报错

9. 断点不走

10.我的出价报红

11. 竞拍大厅折叠效果与滚动冲突 & 加载完成状态无法上拉加载

12. 加载网络图片失败的页面返回报错(未解决)

13. flutter页面进入后快速返回 报错

14. list. first 或 firstWhere报错 List firstWhere Bad state: No element

15. 我的出价页面滑动太灵敏

16. 禁用侧滑

17. ListView底部 iOS有间距,但Android没有


1、easy_refresh相关问题

a. 仅有下拉刷新,viewModel可以不需要控制刷新状态。不用传controller

b. 传controller,在请求成功和失败后,都需要自行去管理刷新状态

问题一:我的出价多次快速切换按钮,调用下拉刷新,onRefresh方法不回调

解决方案:

controller.callRefresh(duration: const Duration(milliseconds: 1), force: true);

问题二:下拉刷新,添加筛选项,回到列表页,上划列表,请求被取消  

原因:ClassicHeader和ClassicFooter 有   triggerOffset, ///触发器任务的偏移量  和 maxOverOffset, ///最大超限偏移,将不再滚动

 解决方案:将两个值设置成相同,则会在滑到 “松开刷新” 的状态时,松手的一刻就回调   onRefresh 和 onLoad 方法。

triggerOffset: 100,  ///触发器任务的偏移量
maxOverOffset: 100,  ///最大超限偏移,将不再滚动

问题三:列表请求下一页,去重后数据少于1条,底部显示加载完成,且上拉加载无效,列表下滑一点再上拉才可以。

解决方案:关闭无限滚动 infiniteOffset设为null,默认值70

2、 父子作用域关联问题

问题:AScope创建BScope,BScope中调用A的ViewModel,与AScope的ViewModel,不是同一个。

现象:竞拍大厅使用Scope,筛选后竞拍大厅未同步筛选项

解决方案:

子作用域创建时需将父作用域的container传过来,并实现parent方法,即实现了父子作用域绑定关系

3. 刘海屏底部安全距离

a. ScreenUtil().bottomBarHeight 获取到的值为0,建议不再使用

b. 可以使用 MediaQuery.of(context).padding.bottom, 获取的值正常

c. AppUtil中提供了safeBottom方法

由于调用该方法会监听context,当下个页面存在输入框时,拉起关闭键盘都会重新rebuild页面,导致ui闪动。因此将bottom的获取放到app初始化时,且仅获取一次(判空逻辑改为copyWith应该也行)

4. 了解保证金弹窗 iOS端闪退 (待优化)

a. demo中debug、profile正常运行

b. 经销商app源码接入后,正常运行

c. 经销商app framework接入后,运行闪退

调用路径:webview_flutter => plugin webview_flutter_wkwebview => native wkwebview

暂未发现经销商app影响调用功能的代码。闪退的堆栈中,number类型调用字典取值方法导致的闪退,FLTWebController为三方的plugin方法实现。为不影响上线,iOS改用原生弹窗。

5. loading无法消失

搜索页加载中侧滑返回后,loading无法消失

原因:

  @overridevoid dispose() {disposed = true;CommonRequest().remove(this);AppUtil().dismissLoading(); // 优化后代码super.dispose();}

dispose时移除了请求监听,导致onDone,onError没有监听回调,loading dismiss方法也就不会触发

因此在移除请求监听时,手动dismiss loading即可。

6. dialog蒙版问题

a. flutter无法给底部tab添加蒙版

解决方案:增加plugin方法调用原生

@async void setTabBarMasker(bool hidden);

b. 弹窗后触发引导切换到其他tab, 蒙版无法消失

c. 多级flutter页面 iOS侧滑后,弹窗在前一个页面未dismiss

解决方案:增加flutter plugin :

void dismissSmartDialog();/// tab切换 dismiss已弹出的dialog@overrideFuture<void> dismissSmartDialog() async {await SmartDialog.dismiss();await SmartDialog.dismiss();await SmartDialog.dismiss();}

原生切换tab,或flutter页面侧滑时,移除dialog(一般不会超过三个,容错移除三次,简单粗暴)

遇到问题:首次进入app,快速切换底部tab,蒙层不消失

原因一 猜您喜欢请求有滞后,切换到其他tab后,请求才成功并触发原生弹出蒙层。

解决方案:添加pageshow provider,同时监听pageshow provider和引导显示的provider

visible: ref.watch(showGuideOfGuessLikeProvider) && ref.watch(isPageShowProvider),

原因二:生命周期未成对出现。

页面首次创建时并没有执行pageShow,pageShow方法是我们自己添加的渲染帧调度监听触发的。

  @overridevoid initState() {WidgetsBinding.instance.addPostFrameCallback((timeStamp) {if (!mounted) {return;}if (needPageObserver() && BoostNavigator.instance.isTopPage(context)) {onPageShow();}onFirstFrame();});super.initState();}

方案二: 改用全局弹窗,router:custom_dialog,present一个半透明弹窗,可以遮盖tabbar

参考 放弃收购弹窗。

遇到问题一: 弹窗pop后,前一个页面loading卡帧,无法消失

解决方案:push.then 后移除loading

建议使用方案二,但不要认为方案二遇到的问题会比方案一少,需要注意flutter各种奇奇怪怪的问题

7. 倒计时优化

a. 列表使用的全局定时器,widget频繁监听,影响性能

解决方案:pageHide移除监听,列表倒计时结束移除监听。

b. 报错Bad state: Cannot use "ref" after the widget was disposed.

原因: 列表快速滚动,调用ref代码时widget已经被释放了

解决方案:onPageShow调用ref前先判断ref.context.mounted为true。(未从根源上解决问题)

mounted解释说明:

在Flutter中,`mounted`是一个布尔类型的变量,它表示当前State对象是否已经被插入到树中去了。当这个State对象被添加到树中时,`mounted`变量就会被设置为`true`。如果State对象被删除,那么`mounted`变量就会被设置为`false`。

开发者可以使用`mounted`变量来判断当前的State对象是否还有效,如果`mounted`为`true`,则可以安全地调用`setState()`方法进行状态更新。如果`mounted`为`false`,则不应该调用`setState()`,因为这个State对象已经被从树中删除了,状态更新将不会生效。

参考 BidHallItemChildCountDown

@override
void watchGenerateViewModel(WidgetRef ref) {super.watchGenerateViewModel(ref);remainSeconds = model.awayFromEnd! - DateTime.now().millisecondsSinceEpoch ~/ 1000;/// 监听定时器刷新 PageHide不监听if (ref.watch(shouldWatchTimerProvider) && remainSeconds > 0) {ref.watch(commonTimer);}
}@override
void onPageHide() {super.onPageHide();ref.read(bidHallItemViewModelProvider).updateShouldWatchTimer(false);
}@override
void onPageShow() {super.onPageShow();if (ref.context.mounted){ref.read(bidHallItemViewModelProvider).updateShouldWatchTimer(true);}
}@override
bool needPageObserver() {return true;
}

根本原因是生命周期未成对出现,渲染帧调度监听添加mounted判断后再触发onPageShow,同6-原因二,优化后onPageShow不需要再判断mounted

8. scrollController.offset报错

a.scrollController加到了easy_refresh的scrollController上,应该是widget的controller

b.列表加了scrollController,但是空视图页面没有加scrollController

9. 断点不走

检查下新加的代码,有可能在断点前面的代码抛异常了

10.我的出价报红

报错日志:如下图所示

flutter: The following assertion was thrown:
flutter: Tried to change the number of overrides. This is not allowed – overrides cannot be removed/added,
flutter: they can only be updated.
flutter: 'package:riverpod/src/framework/container.dart':
flutter: Failed assertion: line 373 pos 7: '_debugOverridesLength == overrides.length'

原因:

You didn't create two separate ProviderScope. The second one updated the first one.

If you want two different scope, give them a different Key

issue 链接: "Tried to change the number of overrides" when running golden tests on multiple widgets with different ProviderScopes · rrousselGit/riverpod · Discussion #2804 · GitHub

解决方案:给ProviderScope添加不同的key

ListView.builder(controller: viewModel.scrollController,itemCount: itemVMList.length,itemBuilder: (BuildContext context, int position) {return _buildChildItemProvider(itemVMList, position);}),DealerItemProvider? _buildChildItemProvider( List<DealerItemViewModel> myPriceList, int position) {if (widget.myPriceType == Const.BIDING) {  ///竞拍中if (myPriceList[position] is ItemBiddingChildVM) {return DealerItemProvider(key: const Key('ItemBidding'), ///需要设置不同keyitemOverrides: overrideItemBiddingChildVM(model: myPriceList[position] as ItemBiddingChildVM,index: position),child: ItemBiddingChild(),);} else if (myPriceList[position] is CommonRecommendTitleViewModel) {return DealerItemProvider(key: const Key('CommonRecommend'), ///需要设置不同keyitemOverrides: overrideCommonRecommendTitleViewModel(model: myPriceList[position] as CommonRecommendTitleViewModel,index: position),child: CommonRecommendTitleWidget());} else if (myPriceList[position] is BidHallItemViewModel) {return DealerItemProvider(key: const Key('CommonRecommend'), ///需要设置不同keyitemOverrides: overrideBidHallItemViewModel(model: myPriceList[position] as BidHallItemViewModel,index: position),child: BidHallItem());}}return null;
}

11. 竞拍大厅折叠效果与滚动冲突 & 加载完成状态无法上拉加载

a. 折叠效果通过NestedScrollView实现,列表刷新数据后滚动到顶部是在list添加scrollController实现,二者相冲突,只有一个生效

b. 列表请求多页数据,筛选第一页数据后,最下面显示加载完成,无法上拉加载。

解决方案: NestedScrollView添加key,触发请求前调用NestedScrollView滚动到顶部的方法

注意:调用innerController.jumpTo(0) 固定收起折叠样式。调用outerController.jumpTo(0); 固定展开折叠样式。因此需判断当前折叠状态。

final GlobalKey<NestedScrollViewState> scrollKey = GlobalKey<NestedScrollViewState>();
/// 触发下拉刷新 手动滚动到顶部
void refreshDataWithAnimate() {if (pageState != ViewState.BUSY){if (collapsedState){scrollKey.currentState?.innerController.jumpTo(0);}else{scrollKey.currentState?.outerController.jumpTo(0);}}refreshData();
}

c. 偶现 首次初始化列表 折叠区域(豆腐块),一直处于折叠状态,无法展开。

原因:静态常量声明使用了.w, 初始化时,scaleWidth有概率为0。原因是screenUtil初始化落后于静态常量初始化导致的

解决方案: 暂时这里不使用静态常量 

根本解决方案:

I. 静态常量不使用.w

II. 更改定义方案,改为变量属性,总之让调用.w晚于screenUtil初始化

12. 加载网络图片失败的页面返回报错(未解决)

​
flutter: ══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞═════════════════════════════════════════════════════════
flutter: The following StateError was thrown:
flutter: Bad state: Failed to load https://pic4.zhimg.com/100/v2-1c0788ea29fe3adaa98ff4ac0.jpg.
flutter:
flutter: When the exception was thrown, this was the stack
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
flutter: Another exception was thrown: Bad state: Failed to load https://pic4.zhimg.com/100/v2-1c0788ea29fe3adaa98ff4ac0.jpg.

原因: 加载图片ExtendedImage.network,页面返回时,重新调用了load方法,报错,且会有堆栈上传。

13. flutter页面进入后快速返回 报错

 [SmartDialog] 'package:flutter/src/widgets/routes.dart': 
Failed assertion: line 1579 pos 12: '_scopeKey.currentState != null': 
Tried to add a willPop callback to a route that is not currently in the tree.

原因:withContainer为false时,不新开container,页面创建太快,立刻点击返回,触发willpop,而此时树中还没有这个路由,因此报错(若解释不对请修正)

解决方案:push flutter页面withContainer改为true。

14. list. first 或 firstWhere报错 List firstWhere Bad state: No element

列表为空数组,调用first方法会崩溃。

列表调用firstWhere 找不到数据也会崩溃。

建议使用列表扩展中的safeFirst 和safeFirstWhere方法。

15. 我的出价页面滑动太灵敏

原因:Tabbar->TabBarView->pageController(PageView->controller) 滚动有动画,时间300ms,滑动切换tab后,动画还没停止,上滑的时候,动作依然被pageController接管,导致上滑触发了左右滑动。

解决方案: 使用ExtendedTabBarView

/// 构建我的出价 子页面
Widget _buildChildList() {return Container(color: themeColors.common_bg2_color,padding: EdgeInsets.only(bottom: Platform.isAndroid ? 90.w : 0),child: ExtendedTabBarView(physics: const LessSpringClampingScrollPhysics(),shouldIgnorePointerWhenScrolling:false,link: false,controller: viewModel.tabController,children: _getTabKeepAliveList(),),);
}

16. 禁用侧滑

方式一:路由push增加参数  'disablePopGesture': true,

方式二:动态禁用侧滑

final PageInfo? pageInfo = RouteNavigator.getPageInfoByContext(ref.context);
BoostChannel.instance.disablePopGesture(containerId: pageInfo?.uniqueId ?? '');

17. ListView底部 iOS有间距,但Android没有

原因: iOS底部有安全距离,安卓没有,原因代码如下:

解决方案:ListView设置padding为zero

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • PFC理论基础与Matlab仿真模型学习笔记(1)--PFC电路概述
  • Android AlertDialog圆角背景不生效的问题
  • 漏洞挖掘 | Selenium Grid 中的 SSRF
  • dockerfile案例
  • js中的条件控制语句
  • MySQL从入门到精通
  • 【智路】智路OS Perception Camera Service
  • 中间件安全(二)
  • B2B2CJava商城如何提高二次开发能力
  • IEC101、IEC103、IEC 104区别
  • 《黑神话悟空》开发框架与战斗系统解析
  • 达梦数据库sql日志说明
  • 深蓝学院-- 量产自动驾驶中的规划控制算法 小鹏
  • 监控易监测对象及指标之:全面监控GBase数据库
  • 【MySQL】MySQL和Workbench版本兼容问题
  • [译]前端离线指南(上)
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • Apache Zeppelin在Apache Trafodion上的可视化
  • Docker 笔记(2):Dockerfile
  • flask接收请求并推入栈
  • Python - 闭包Closure
  • Vue 动态创建 component
  • Vue2 SSR 的优化之旅
  • 安卓应用性能调试和优化经验分享
  • 百度地图API标注+时间轴组件
  • 分布式事物理论与实践
  • 前嗅ForeSpider教程:创建模板
  • 如何使用 JavaScript 解析 URL
  • 少走弯路,给Java 1~5 年程序员的建议
  • 事件委托的小应用
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 移动端 h5开发相关内容总结(三)
  • 用mpvue开发微信小程序
  • 云大使推广中的常见热门问题
  • Spring Batch JSON 支持
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • ​​​​​​​开发面试“八股文”:助力还是阻力?
  • ​ArcGIS Pro 如何批量删除字段
  • ​浅谈 Linux 中的 core dump 分析方法
  • ​水经微图Web1.5.0版即将上线
  • #pragma预处理命令
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (Windows环境)FFMPEG编译,包含编译x264以及x265
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (zt)最盛行的警世狂言(爆笑)
  • (二)linux使用docker容器运行mysql
  • (二十九)STL map容器(映射)与STL pair容器(值对)
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • .NET开发不可不知、不可不用的辅助类(一)
  • .skip() 和 .only() 的使用
  • /boot 内存空间不够