为何有这篇文章?java
这篇文章能够说是我的Flutter问题随笔吧,虽然Flutter能够方便的作到跨平台,可是毕竟是新项目,功能没那么全面也是意料之中,因此在此记录跟踪一下目前在使用Flutter过程当中遇到的问题,目前的解决方案,并跟踪记录一下。android
问题列表(持续更新):git
这个源自于我的练手APP,在开发阅读模块过程当中遇到了这么一个问题:github
若是想要自定义文字间距,段落间距等,那么天然就要使用textPainter本身绘制文字。可是由此引起出一个问题:若是有上万个文字,那么测绘时间会很长。天然会阻塞主进程。canvas
解决这个问题,第一个想法天然就是使用异步处理,那么flutter 中的异步方案有哪些呢?缓存
按照官方文档,大量计算东西应该放到Isolate中,因此,天然而然地,咱们将textPinter测绘方法放到Isolate中执行,可是呢,执行报错:native function not foundbash
缘由就是UI包的类只容许在Flutter的UI Isolate中执行。服务器
此题无解,完结撒花,各回各家,各找各妈(才怪)异步
解决方案一:Pluginasync
这个方法的思路来自于官方开发人员的回答:
right now you would have to write your own line-breaking logic - perhaps as a plugin. We don't currently have any API for doing text layout in a separate isolate. @GaryQian might have some other idea about this too.
因此说,咱们看下官方的Plugin是怎么实现的。
在 Plugin工程中,有这么一个: android_alarm_manager ,这个Plugin中的AlarmService.java文件中,有这么一个方法:startBackgroundIsolate(要素察觉+1)
经过阅读源码,咱们得知,其实说白了就是新建一个FlutterNativeView ,这个FlutterNativeView 不负责渲染界面,只负责当后台线程来用。一样的道理,咱们也能够用一样的方法来处理咱们的须要运行在UI Isolate的异步任务。(至于为何新建一个FlutterNativeView ,就能实现这个需求,粗略的说下是由于,每次新建FlutterNativeView,其实都会新建一些TaskRunner,其中就包含UI 的TaskRunner,总之有兴趣的能够搜下Flutter中的TaskRunner机制了解下)
不过,其实不用本身实现注册,有这么一个第三方:flutter_isolate能够作到这点,用法跟普通的isolate差很少,因此解决方式也很简单:找到原来使用Isolate的那段代码,把Isolate.spawn替换为FlutterIsolate.spawn便可。不过通过测试,在1.10版本上会报错,因此想使用这个方式的话,仍是切回stable 分支使用吧。
解决方案二:分割为多个小任务(我的感受不太推荐这种方式,感受不可控,毕竟假如小任务的执行时间也很长咋办)
这种方式说白了就是每测绘完一行,就提交一次,而不是总体测绘完以后再提交结果。
举个小例子:
Future(() async {
var result;
for (var i = 0; i < 1000000; ++i) {
result = 'result is $i';
await Future.delayed(Duration.zero);
}
print(result);
});
复制代码
用这种方式计算就不会卡UI
解决方案三:目前这个问题已经加入到里程碑了,在将来的某天应该就有解决方案
也就是像音乐播放器那样,会有个通知显示进度,即便在桌面也能够播放音乐这种
目前只有Android的实现,IOS这块目前尚未方案……%
找了半天才发现有个大佬已经搞定了这个问题:
使用extended_nested_scroll_view便可解决这个问题,在此记录一下
这个描述可能有些抽象,具体状况以一个例子为例描述:
1、首页放一个图片,给他设置点击跳转详情页,并设置hero动画。
2、将图片设置为SliverAppBar的FlexibleSpaceBar的widget中的内容,而后上拉页面,折叠隐藏掉SliverAppBar。
3、按后退键退出详情页,触发hero的关闭动画。
按这三步执行以后,首页原来那张图片就变成空白,并且没法点击。
issue:
因此切换到master分支或者dev分支(问题修复版本v.1.10.14),或者下降稳定版的版本。
下面是我搜索出的内容:
stackoverflow.com/questions/5…
上面的实现方法各有千秋吧,整理一下主要的缺陷点,之后能够根据实际状况使用:
如今正在尝试解决ScrollablePositionedList中的视差滑动问题,(得想个办法让NestScrollView届的到ScrollablePositionedList的controller) 在NestScrollView中是经过设置PrimaryScrollController,让innerController管理body滑动的,因此使用这个innerController来替代ScrollablePositionedList的controller便可解决没法滑动的问题,可是随之而来的是一个新的问题,如今按index跳转,会致使body触发滑动,进而直接折叠掉SliverAppBar……………如何让index跳转的时候,body在NestScrollView中的位置不动,只在原地实现自身的index跳转,只有手动滑动的时候才容许改变body在NestScrollView中的位置,目前想法是在SliverAppBar的floating、pinned等控制滑动方式的方法上看看有没有突破口。 不搞了,如今挺好的。直接满屏展现,实在不行加个跳转到顶部按钮,我感受蛮合理的。(大雾)
改变高度这个,目前采用设置addPersistentFrameCallback 方式持续监听。本觉得应该性能比较差,可是测试了一下,好像frame没啥变化,因此应该没啥问题。
有些同窗可能对我为何须要测量上万字感到困惑,因此在这简单的提下:
测绘上万字这个状况来自于我想把本身原来的一个Android原生小说阅读器,转换为flutter实现(主要是想实现那帮仿真、滚动等翻页动画啥的,练习一下flutter的canvas操做),小说阅读器的基本思路参考自这个项目:任阅。
思路基本是这样的:
基本功能是:上一页,下一页,上一章,下一章,章内跳页。
由于要考虑上一章下一章切换以及章内跳转到多少页的这些功能,因此天然以章为基础单位,章内部包含页,取的时候把章的数据拿出来,而后从章中页数据中取出要展现的页的数据,并将其绘制到canvas上。
因此,缓存计算也是计算的章的内容,因此当从服务器下载下来新的章的时候,就有可能遇到上万字的章的状况。
可能也有同窗说:直接按页缓存不就好了,每次只缓存几页的内容,那确定不会遇到须要一次性测量上万字的状况。可是若是纯粹按页缓存的话,若是遇到这两种状况就傻眼了:1. 若是有个用户打开一本新的小说,直接跳到第十章,而后按了上一页。 2. 章节内跳转到第n页(n>缓存页数)。
由于标点符号、全角、特殊字符等非普通汉字的存在,因此咱们是没法直接得知每页展现的内容,天然没法在测量完整章以前得知某页的展现内容,因此要支持上面提到2个状况,必然要测量分页整章内容。
固然,可能我这个思路也不是最优解,若是有更好的方案,但愿各位不吝指教