关于flutter:Flutter自定义相机Flutter相册选择照片

题记 —— 执剑咫尺,从你的点滴积攒开始,所及之处,必精益求精。 github?测试源码在这里百度同步CSDN网易云课堂教程掘金EDU学院教程知乎Flutter系列文章 头条同步 理论我的项目开发中,谷歌官网举荐的几个相机插件总是满足不了须要,更令人不难受的是在华为某些高版本系列的手机中应用零碎相机拍照或者是抉择照片会让利用闪退。 小编也剖析了起因,在这些手机拍照的照片过大,在手机相机拍完的那一瞬间,手机零碎还没有解决完照片,而后利用就去读取这个照片,导致系统异样解体。 至本插件编写的 0.0.1 版本时,各相机利用插件都未修复其兼容性,以小编的性情,那就是再造个轮子,于是乎 本插件就诞生了。 0.0.1 版本 只反对 Android (已公布 2020-09-09)0.0.3 版本 同时反对 iOS (正在公布中)0.0.8 版本 反对 Android 自定义 拍照页面 (正在公布中)0.0.9 版本 反对 iOS 自定义 拍照页面 (正在公布中)如下图是默认状况下自定义相机的页面成果: 1 增加依赖小编以将这个自定义相机封装成一个插件组件,间接应用flutter_custom_camera_pugin插件就可应用,个别小编的风格就是提供两种集成形式如下: 通过pub仓库增加依赖,代码如下:最新版本查看这里 dependencies: flutter_custom_camera_pugin: ^0.0.1或者是通过 github 点击查看github形式增加依赖,代码如下: dependencies: shake_animation_widget: git: url: https://github.com/zhaolongs/FlutterCustomCameraPugin.git ref: master而后加载依赖,代码如下: flutter pub get而后在应用的中央导包,代码如下: import 'package:flutter_custom_camera_pugin/flutter_custom_camera_pugin.dart';2 关上自定义相机 拍照你能够应用 FlutterCustomCameraPugin 的 openCamera 办法来关上自定义相机拍照页面,其中 可选参数 cameraConfigOptions 用来配置自定义相机页面的的按钮是否显示,如下代码清单 2-1: ///代码清单 2-1 ///关上相机 void openCamera() async { CameraConfigOptions options = new CameraConfigOptions(); ///默认自定义相册是否显示 相册切换 options.isShowSelectCamera = true; ///默认自定义相册是否显示 前后镜头切换 options.isShowPhotoAlbum = true; ///默认自定义相册是否显示 闪光灯开关按钮 options.isShowFlashButtonCamera = true; ///调起自定义相机 ///拍照的返回后果 CameraResultInfo resultInfo = await FlutterCustomCameraPugin.openCamera(cameraConfigOptions: options); if (resultInfo.code == 200) { imageFile = new File(resultInfo.data["lImageUrl"]); }else if (resultInfo.code == 201) { ///201 是拍照勾销 如点击了敞开按钮 ///或者是 Android 手机的后退按钮 } setState(() {}); }CameraConfigOptions 用来配置相机参数,如下所示: ...

September 9, 2020 · 1 min · jiezi

关于flutter:Flutter-实战各种各样形状的组件

老孟导读:Flutter中很多组件都有一个叫做shape的属性,类型是ShapeBorder,比方Button类、Card等组件,shape示意控件的形态,零碎曾经为咱们提供了很多形态,对于没有此属性的组件,能够应用 Clip 类组件进行裁减。BeveledRectangleBorder斜角矩形边框,用法如下: RaisedButton( shape: BeveledRectangleBorder( side: BorderSide(width: 1, color: Colors.red), borderRadius: BorderRadius.circular(10)), child: Text('老孟'), onPressed: () {},) 如果设置的半径比控件还大,就会变成菱形: 3RaisedButton( shape: BeveledRectangleBorder( side: BorderSide(width: 1, color: Colors.red), borderRadius: BorderRadius.circular(100)), child: Text('老孟'), onPressed: () {},) 同理,如果半径设置为0,就是矩形。 RaisedButton( shape: BeveledRectangleBorder( side: BorderSide(width: 1, color: Colors.red), borderRadius: BorderRadius.circular(0)), child: Text('老孟'), onPressed: () {},) BorderBorder容许独自设置每一个边上的线条款式. RaisedButton( shape: Border( top: BorderSide(color: Colors.red,width: 2) ), child: Text('老孟'), onPressed: () {},) ...

September 9, 2020 · 4 min · jiezi

关于flutter:Flutter-2020-学习心得学习路线

视频https://www.bilibili.com/vide... 新人上手状况语言根底数据结构网络通信前端布局动画优化点前端遇到的最大问题原生调试原生组件开发聊聊学习动机单位工作须要本人趣味开发 APP毕业设计漫无目的、漫无目的的学习学习路线https://github.com/olexale/fl... 资源官网 darthttps://dart.dev/guides/langu...官网 flutterhttps://flutter.dev/https://flutter.cn/juejinhttps://juejin.im/tag/Fluttermediumhttps://medium.com/tag/flutterflutter awesome githubhttps://github.com/Solido/awe...https://github.com/crazycodeb...flutter awesome webhttps://flutterawesome.com/otherhttps://twitter.com/search?q=...https://www.facebook.com/sear...总结最快的学习形式有个指标、看优良源代码,实现你的作品、上线! © 猫哥 https://ducafecat.tech https://ducafecat.gitee.io

September 4, 2020 · 1 min · jiezi

关于flutter:我对Flutter的第一次失望

老孟导读:此文翻译自:https://medium.com/@suragch/m...我喜爱Flutter。我喜爱开发一次并让代码在Android和iOS上运行。我喜爱节俭多少工夫。我喜爱当初成为一名Web开发人员,而无需做任何额定的工作。我喜爱hot reload。我喜爱通过将小部件组合到布局中来疾速构建UI。我喜爱制作ListView简略得多。我喜爱状态治理。 (好吧,只是在开玩笑。然而我能够应酬。)我喜爱Dart。我喜爱Future和async / await比Android AsyncTasks甚至iOS Dispatch Queue容易得多。 然而,在花了最初两周的工夫钻研Flutter如何出现文本后,我对应用的工具感到悲观。 咱们被告知: Flutter的分层体系结构使您能够管制屏幕上的每个像素。这显然不适用于用于绘制文本的像素。 Flutter中的低级文字性能Flutter应用名为LibTxt的库联合应用Skia,Hafbuzz,Minikin和ICU来出现文本。开发人员在应用Text小部件或TextSpan甚至是TextPainter工夫接应用它。在最低级别上,咱们能够应用dart:iu,它是应用ParagraphBuilder构建的Paragraph类。这些类基本上只是底层LibTxt引擎的包装器。简直所有工作都由此引擎实现,而在dart:ui中简直没有裸露。 Paragraph类为咱们提供了以下管制: Size:我能够获取整个渲染段落的宽度和高度,它能够是单行或多行。距基线的间隔(仅对于第一行)文本是否溢出了maxLines变量。文本框的大小和绝对地位。这是一个例子: 最靠近某个像素地位的文本字符索引。在下面的示例中,像素(1、1)对应于字符串中的索引0,即“My text line.”的字母“ M”。字符串中某些字符偏移的单词边界。随后的更新也为咱们提供了LineMetrics,它为每行提供了许多详细信息: class LineMetrics { final bool hardBreak; final double ascent; final double descent; final double unscaledAscent; final double height; final double width; final double left; final double baseline; final int lineNumber;} 然而,咱们没有失去: 一种在文本框中获取理论文本的办法。一种管制文本布局形式的办法。一种在门路上绘制文本的办法。一种无需绘制整个段落即可测量和绘制短文本的办法。一种从文本字符串获取换行地位的办法与Android和iOS的比拟在Android中,只管大多数人会应用TextView,然而您能够通过应用StaticLayout,Canvas和Paint类取得低级控件来执行下面列出的所有操作。以下是可用的泛滥选项中的几个: Canvas.drawTextOnPath)Canvas.drawTextRun)Paint.getFontMetrics)Paint.measureText)我在iOS上没有那么低级的文字绘制教训(因为我认为我只会学习在Flutter中做所有事件),然而Core Text具备丰盛的工具集。 Flutter 指南中如此说: 以多个平台为指标的SDK是很常见的……提供可在所有指标平台上运行的API。可怜的是,这通常意味着一个平台或另一个平台独有的性能不可用。对于Flutter,咱们心愿通过明确地成为每个平台的最佳开发方式来防止这种状况。咱们在跨平台上应用的能力仅次于咱们在每个平台上应用的能力。 (增加了重点) 以后,对于须要在应用程序中进行低级文本渲染的咱们当中,Flutter并不是最好的开发平台。 用例您可能会说Flutter曾经提供了Text和RichText小部件。是的,他们十分好。他们将满足99.9%的开发人员的需要。然而,存在应用较低级别的文本出现工具的用例。 蒙文我的用例是布局并渲染传统的蒙古文字,该文字垂直书写,并从左到右换行。英语是侧身书写,但CJK和表情符号字符应放弃其失常方向。 有一些应用小部件组合的“解决方案”,然而当您增加文本款式的须要时(例如通过在文本的右侧绘制一条垂直线来“下划线”),一种更牢靠的解决方案是解决所有文本手工测量,安排和绘画。我曾经开始在这里工作了。 中文,日文和韩文中文,日文和韩文也能够按各种垂直方向进行布局。像蒙古语一样,有一种解决办法,能够解决一次性状况,但对于罕用用法,渲染包会更有帮忙。浏览此内容以更具体地形容需要。 Flutter仅反对反对从右到左和从左到右的布局。不反对(也不反对????)垂直布局。我不会对此示意狐疑。有很多工作。然而我心愿他们会给咱们更多工具来本人做。 艺术文字进行文字绘画的应用程序也将从对文字绘画工具的低级别拜访中受害。 ...

September 4, 2020 · 1 min · jiezi

关于flutter:Flutter-布局系统概述

老孟导读:此篇文章十分具体的解说了 Flutter 布局零碎的工作原理。翻译自:https://itnext.io/flutter-lay... 最近,我决定专一于Flutter基础知识。这次,我试图更好地了解“布局零碎的工作原理”,并答复以下问题: 我的小部件的尺寸看起来不适合,怎么回事?我只想将Widget搁置在特定地位,然而没有任何属性能够管制它,为什么呢?我始终看到诸如BoxConstraints,RenderBox和Size之类的术语。它们之间有什么关系?对布局零碎如何工作有一个大略的理解?本文并不意味着对以上所有内容进行深刻而具体的形容。然而,咱们将对最重要的内容进行很好的概述,力求将所有可视化。 “两个阶段” 布局零碎和束缚首先,小部件是Flutter SDK的构建块,但它们不负责将其本身绘制到屏幕中。每个小部件都与负责此操作的RenderBox对象相关联。这些框是2D直角坐标系,其大小示意为距原点的偏移。每个RenderBox还将与一个BoxConstraints对象相关联,该对象蕴含四个值:最大|最小宽度和最大|最小高度。 RenderBox能够抉择具备所需的任何大小,但它必须恪守这些值/束缚。小部件的大小/地位齐全取决于这些RenderBox的属性。 原文:The same way Widgets build a Widget three, RenderBoxes make a render three.我感觉three可能写错了,应该是tree,译文:以同样的形式小部件生成 组件树,RenderBoxes生成渲染树。 咱们能够将Flutter的布局零碎视为两阶段零碎。在第一个阶段中,framework 以递归地形式沿着渲染树 把BoxConstraints传递给子组件。它为父组件提供了一种形式来调节/增强子组件的尺寸,并依据须要更新这些限度。换句话说,这是负责流传束缚信息的阶段,让每个人晓得其最大/最小值。 实现后,第二阶段开始。这次,每个RenderBox都将其抉择的大小传递回其父对象。父级收集所有子级的大小,而后应用此几何信息将每个子级正确定位在本人的笛卡尔零碎中。这个阶段负责确定大小和地位,在此阶段,父组件晓得每个子组件的大小以及他们的地位。 那么,这到底意味着什么? 这意味着父组件有责任定义/限度/束缚子组件的尺寸,并绝对于其坐标系进行定位。换句话说,小部件能够抉择其大小,然而它必须始终恪守从其父级收到的束缚。此外,小部件不晓得其在屏幕上的地位,但其父级晓得。 如果您对小部件的大小或地位有疑难,请尝试查看(更新)其父组件。 Example好的,让咱们将所有内容可视化,尝试通过示例理解正在产生的事件。然而在此之前,以下是一些在调试束缚时可能有用的术语, 上面的术语未翻译,因为这些术语自身比译文更好了解: If max(w|h) = min (w|h)*, that is tightly* constrained.If min(w|h) = 0*, we have a loose* constraint.If max(w|h) != infinite*, the constraint is bounded.*If max(w|h) = infinite*, the constraint is unbounded.*If min(w|h) = infinite*, is just said to be infinite* ...

September 2, 2020 · 2 min · jiezi

关于flutter:Flutter中Contrainer-组件的宽高限制分析

题记 —— 执剑咫尺,从你的点滴积攒开始,所及之处,必精益求精,即是折腾每一天。 **你可能须要CSDN网易云课堂教程掘金EDU学院教程知乎Flutter系列文章 头条同步百度同步本文章首发于微信公众号(biglead) 我的大前端生涯 ,同步登载各技术论坛。 1 Contrainer 组件在 flutter 利用程序开发中,Contrainer组件能够了解为容器,罕用用来设置背景、设置一个 Widget 的内外边距、以及边框款式等等。 2 Contrainer 组件的根本应用以及大小限定剖析Contrainer 组件的大小限定能够形容为: 当 Contrainer 组件的父布局设置了大小,那么 Contrainer 将应用父布局的大小设置,如果 父布局没有设置大小 ,本身设置了大小,那么 Contrainer 将应用本身设置的大小,如果 本身没有设置大小,那么 Contrainer 将包裹子 Widget 或者说是将应用子Widget 的大小设置在这里 黄色的 Contrainer 与 灰色的 Contrainer 的大小齐全一至,而灰色的 Contrainer 的大小是由父黄色的Contrainer设置的大小(200,200)决定的, 本身设置的(100,100),并没有起到影响, 子Widged SizedBox 设置的大小(50,50)也没有影响 父组件 灰色的 Contrainer 的大小。 import 'package:flutter/cupertino.dart';import 'package:flutter/material.dart';class ContainerHomePage extends StatefulWidget { @override State<StatefulWidget> createState() { return ContainerHomePageState(); }}class ContainerHomePageState extends State { @override Widget build(BuildContext context) { return Scaffold( appBar: new AppBar( title: Text("Container 配制"), ), body: Center( ///内三组件 child: Container( ///Container 默认包裹子widget (没任何内外大小的限度 ) ///Container的背景色彩 width: 200, height: 200, ///黄色 color: Colors.yellow, ///当Container 的外层有大小限度进 Container取用的是外层设置的大小 ///内二组件 child: Container( ///灰色 color: Colors.grey, width: 100, height: 100, ///内一组件 child: SizedBox( width: 50, height: 50, child: Text("这里是body "), ), ), ), ), ); }}Container 的大小由子 本身设置 的状况剖析在这里 黄色的 Contrainer 与 灰色的 Contrainer 的大小齐全一至,而灰色的 Contrainer 的大小是由本身设置的大小(100,100)决定的, 子Widged SizedBox 设置的大小(50,50)将没有影响 父组件 灰色的 Contrainer 的大小。 ...

September 2, 2020 · 2 min · jiezi

关于flutter:Flutter-实战17篇动画系列文章带你走进自定义动画

老孟导读:Flutter 动画系列文章分为三局部:根底原理和外围概念、零碎动画组件、8篇自定义动画案例,共17篇。动画外围概念在开发App的过程中,自定义动画必不可少,Flutter 中想要自定义动画,首先要了解 Flutter 动画实现的基本原理及相干概念。 第1-4篇介绍了 Flutter 动画中最重要的三个概念以及三者之间的关系: AnimationController:动画控制器,管制动画的播放、进行等。继承自Animation< double >,是一个非凡的Animation对象,默认状况下它会线性的生成一个0.0到1.0的值,类型只能是 double 类型,不设置动画曲线的状况下,能够设置输入的最小值和最大值。Curve:动画曲线,作用和Android中的Interpolator(差值器)相似,负责管制动画变动的速率,艰深地讲就是使动画的成果可能以匀速、减速、加速、抛物线等各种速率变动。Tween:将 AnimationController 生成的 [0,1]值映射成其余属性的值,比方色彩、款式等。第5篇解说了动画序列 TweenSequence,其将多个 Tween 或者 Curve 关联到一个 AnimationController 中。 文章链接: 动画外围-AnimationController:http://laomengit.com/guide/animation/AnimationController.html动画外围-Tween:http://laomengit.com/guide/animation/Tween.html动画外围-Curve:http://laomengit.com/guide/animation/Curve.html动画外围-总结:http://laomengit.com/guide/animation/AnimationSummary.html动画序列 TweenSequence: http://laomengit.com/guide/animation/TweenSequence.html零碎动画组件第6篇介绍了20多种零碎动画组件的用法以及如何选取应用哪一种组件,乍一看20多种零碎动画组件十分多,但其仅分为隐式动画组件 和 显式动画组件 两种,用法根本一样。文章地址:http://laomengit.com/guide/animation/AnimatedWidget.html 第7篇解说 AnimatedList 列表增/删动画组件:http://laomengit.com/guide/animation/AnimatedList.html 第8篇解说 Hero 共享动画组件:http://laomengit.com/guide/animation/Hero.html 第9篇解说 Material motion 动画,Material motion 是 Flutter 1.17 大会上 Flutter 团队公布的新的 Animations 软件包,该软件包提供了实现新的 Material motion 标准的预构建动画:http://laomengit.com/guide/animation/TranslationAnimations.html 自定义动画第10篇案例-自定义路由动画:http://laomengit.com/guide/animation/NavigatorAnimation.html 第11篇案例-“孔雀开屏”的动画成果:http://laomengit.com/guide/animation/Peacock.html 第12篇案例-自定义突变进度条:http://laomengit.com/guide/animation/CircleProgress.html 第13篇案例-自绘玫瑰:http://laomengit.com/guide/animation/Rose.html 第14篇案例-仿掘金点赞:http://laomengit.com/guide/animation/JuejinLike.html ...

September 1, 2020 · 1 min · jiezi

关于flutter:Flutter开发基础Dart语法规范

字符串两个常量字符串(不是变量,是放在引号中的字符串),你不须要应用 + 来连贯它们。举荐的写法 print( 'ERROR: Parts of the spaceship are on fire. Other ' 'parts are overrun by martians. Unclear which are which.');不举荐的写法 print('ERROR: Parts of the spaceship are on fire. Other ' + 'parts are overrun by martians. Unclear which are which.');不要在字符串中应用不必要的大括号如果要插入是一个简略的标识符,并且前面没有紧跟着的字母,则应省略 {} 举荐的写法 'Hi, $name!'"Wear your wildest $decade's outfit."//标识符前面有紧跟着的字母了 加上大括号用以辨别'Wear your wildest ${decade}s outfit.'不举荐的写法 'Hi, ${name}!'"Wear your wildest ${decade}'s outfit."布尔值应用? ?将空值转换为布尔值。当表达式的值能够为真、假或null,并且您须要将后果传递给不承受null的对象时,此规定实用。一个常见的状况是一个判断空值的办法调用被用作条件: 不举荐的写法 if (optionalThing?.isEnabled) { print("Have enabled thing.");}如果optionalThing为空,此代码将抛出异样。(if只反对判断bool值,不反对null)要解决这个问题,您须要将null值“转换”为true或false。尽管您能够应用==来实现此操作,但咱们倡议应用?? : ...

August 31, 2020 · 5 min · jiezi

关于flutter:一文学会Dart事件循环及异步调用

异步代码在Dart中随处可见。许多库函数返回Future对象,您能够注册处理程序来响应事件,如鼠标单击、文件I/O实现和计时。 本文形容了Dart的事件循环架构,您就能够编写出更好的更少问题的异步代码。您将学习如何应用Future,并且可能预测程序的执行程序。 <u>留神:本文中的所有内容既实用于原生运行的Dart应用程序(应用Dart虚拟机),也实用于曾经编译成JavaScript的Dart应用程序(dart2js的输入)。本文应用Dart一词来辨别Dart应用程序和其余语言编写的软件。</u> 在浏览本文之前,你应该相熟Future和错误处理的基本知识。 基本概念如果你写过UI代码,你可能曾经相熟了事件循环和事件队列的概念。它们确保了图形操作和事件(如鼠标点击)一次只解决一个。 事件循环和队列 事件循环的工作是从事件队列中获取一个事件并解决它,只有队列中有事件,就反复这两个步骤。 队列中的事件可能代表用户输出,文件I / O告诉,计时器等。 例如,上面是事件队列的图片,其中蕴含计时器和用户输出事件: 你可能在其余的语言中相熟这些。当初咱们来谈谈dart语言是如何实现的。 Dart的单线程 一旦一个Dart函数开始执行,它将继续执行直到退出。换句话说,Dart函数不能被其余Dart代码打断。 如下图所示,一个Dart程序开始执行的第一步是主isolate执行main()函数,当main()退出后,主isolate线程开始一一处理程序事件队列上的所有事件。 实际上,这有点过于简化了。 dart的事件循环和队列Dart应用程序的事件循环带有两个队列——事件队列和微工作队列。 事件队列蕴含所有内部事件:I/O、鼠标事件、绘图事件、计时器、Dart isolate之间的通信,等等。 微工作队列是必要的,因为事件处理代码有时须要稍后实现一个工作,但在将控制权返回到事件循环之前。例如,当一个可察看对象发生变化时,它将几个渐变变动组合在一起,并同步地报告它们。微工作队列容许可察看对象在DOM显示不统一状态之前报告这些渐变变动。 事件队列蕴含来自Dart和零碎中其余的事件,微工作队列只蕴含来自Dart外围代码的事件。 如下图所示,当main()函数退出时,事件循环开始工作。首先,它以FIFO(先进先出)程序执行所有微工作。而后,它使事件队列中的第一项出队并解决,而后它反复这个循环:执行所有微工作,而后解决事件队列上的下一事件。一旦两个队列都为空并且不会再产生任何事件,应用程序的嵌入程序(如浏览器或测试框架)就能够开释应用程序。 <u>留神:如果web应用程序的用户敞开了它的窗口,那么web应用程序可能会在其事件队列为空之前强行退出。</u> 重要:当事件循环正在执行微工作队列中的工作时,事件队列会卡住:应用程序无奈绘制图形、解决鼠标点击、对I/O做出反馈等。 只管能够预测工作执行的程序,但不能精确预测事件循环何时将工作从队列中移除。Dart事件处理零碎基于单线程循环;它不是基于任何类型的工夫规范。例如,当您创立一个提早的工作时,事件将在您指定的工夫进入队列。他还是要期待事件队列中它之前的所有事件(包含微工作队列中的每一个事件)全副执行完后,能力失去执行。(延时工作不是插队,是在指定工夫进入队列) 提醒:链式调用future指定工作程序如果您的代码有依赖关系,请以显式的形式编写。显式依赖关系帮忙其余开发人员了解您的代码,并且使您的程序更能抵制代码重构。 上面是一个谬误编码方式的例子: // 因为在设置变量和应用变量之间没有明确的依赖关系,所以不好。future.then((){...设置一个重要变量...)。Timer.run(() {...应用重要变量...})。相同,像这样写代码: //更好,因为依赖关系是显式的。 future.then(…设置一个重要的变量…)then((_){…应用重要的变量…});在应用该变量之前必须先设置它。(如果您心愿即便呈现谬误也能执行代码,那么能够应用whenComplete()而不是then()。) 如果应用变量须要工夫并且能够在当前实现,请思考将代码放在新的Future中: //可能更好:显式依赖加上提早执行。future.then(…设置一个重要的变量…)then((_) {new Future((){…应用重要的变量…})});应用新的Future使事件循环有机会解决事件队列中的其余事件。下一节将具体介绍提早运行的调度代码。 如何安顿工作当您须要指定一些须要提早执行的代码时,能够应用dart:async库提供的以下API: Future类,它将一个我的项目增加到事件队列的开端。 顶级的scheduleMicrotask()函数,它将一个我的项目增加到微工作队列的开端。 应用这些api的示例在下一节中。事件队列:new Future()和微工作队列:scheduleMicrotask() 应用适当的队列(通常是事件队列)尽可能的在事件队列上调度工作,应用Future。应用事件队列有助于放弃微工作队列较短,缩小微工作队列影响事件队列的可能。 如果一个工作须要在解决任何来自事件队列的事件之前实现,那么你通常应该先执行该函数。如果不能先执行,那么应用 scheduleMicrotask()将这个工作增加到微工作队列中。 事件队列: new Future()要在事件队列上调度工作,能够应用new Future()或new Future.delayed()。这是dart:async库中定义的两个Future的构造函数。 留神:您也能够应用Timer安顿工作,然而如果Timer工作中产生任何未捕捉的异样,您的应用程序将退出。 相同,咱们倡议应用Future,它建设在Timer之上,并减少了诸如检测工作实现和对谬误进行响应的性能。 要立刻将一个事件放到事件队列中,应用new Future(): //在事件队列中增加工作。new Future((){ /……代码就在这里……});您能够增加对then()或whenComplete()的调用,以便在新的Future实现后立刻执行一些代码。例如,当new Future的工作来到队列时,以下代码输入“42”: new Future(() => 21) .then((v) => v*2) .then((v) => print(v));应用new Future.delayed()在一段时间后在队列中退出一个事件: ...

August 27, 2020 · 2 min · jiezi

关于flutter:Flutter-实战动画序列共享动画路由动画

老孟导读:此篇文章是 Flutter 动画系列文章第四篇,本文介绍动画序列、共享动画、路由动画。动画序列Flutter中组合动画应用Interval,Interval继承自Curve,用法如下: Animation _sizeAnimation = Tween(begin: 100.0, end: 300.0).animate(CurvedAnimation( parent: _animationController, curve: Interval(0.5, 1.0)));示意_sizeAnimation动画从0.5(一半)开始到完结,如果动画时长为6秒,_sizeAnimation则从第3秒开始。 Interval中begin 和end参数值的范畴是0.0到1.0。 上面实现一个先执行色彩变动,在执行大小变动,代码如下: class AnimationDemo extends StatefulWidget { @override State<StatefulWidget> createState() => _AnimationDemo();}class _AnimationDemo extends State<AnimationDemo> with SingleTickerProviderStateMixin { AnimationController _animationController; Animation _colorAnimation; Animation _sizeAnimation; @override void initState() { _animationController = AnimationController(duration: Duration(seconds: 5), vsync: this) ..addListener((){setState(() { });}); _colorAnimation = ColorTween(begin: Colors.red, end: Colors.blue).animate( CurvedAnimation( parent: _animationController, curve: Interval(0.0, 0.5))); _sizeAnimation = Tween(begin: 100.0, end: 300.0).animate(CurvedAnimation( parent: _animationController, curve: Interval(0.5, 1.0))); //开始动画 _animationController.forward(); super.initState(); } @override Widget build(BuildContext context) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ Container( height: _sizeAnimation.value, width: _sizeAnimation.value, color: _colorAnimation.value), ], ), ); } @override void dispose() { _animationController.dispose(); super.dispose(); }}成果如下: ...

August 25, 2020 · 3 min · jiezi

关于flutter:flutter起步时遇到的坑

最近要写app,看很多人用flutter,查了下材料,这个是谷歌出品的框架,谷歌出品必属精品,于是毫无犹豫地就开始搭环境了,然而没想到。。搭环境如此波折,以此记录一下。 依照官网步骤,一顿操作下来猛如虎,到flutter doctor的时候就卡住了, 显示如下谬误✗ Unable to locate Android SDK. Install Android Studio from: [https://developer.android.com/studio/index.html]这个是Android studio编辑器的谬误,无奈导入Android sdk,于是从网上下载了sdk放到本地,并在setting中设置门路,如下图所示这里有个小技巧,developer.android.com在国内无奈失常拜访。解决方案将android.com替换为android.google.cn即可。显示如下信息示意以后没有实在设施连上电脑,不必理睬~毕竟之后能够用模拟器调试不是~所以这里只是正告而已 [!] Connected device ! No devices availableflutter doctor命令都显示胜利之后,满怀期待的关上Android studio,没想到一关上就给我当头一棒,又报错了,报错信息如下解决办法:点cancel,之后点next,在之后的界面会有装置sdk的步骤,急躁等着装置完即可。装置Android studio的dart和flutter插件,下载flutter插件的时候提醒dart插件下载不了解决办法:先装置dart插件,再装置flutter插件即可 创立flutter我的项目的时候,提醒flutter sdk path not given解决办法:“File”->“Setting”->“Languages & frameworks”->“Flutter”抉择装置门路 flutter启动始终卡在running Gradle task 'assembleDebug'解决办法: 批改Gradle的maven的地址,批改为阿里云的镜像地址批改我的项目中android/build.gradle文件,批改之后:buildscript { ext.kotlin_version = '1.3.50' repositories {// google()// jcenter() maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/jcenter' } maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } } dependencies { classpath 'com.android.tools.build:gradle:3.5.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" }}allprojects { repositories {// google()// jcenter() maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/jcenter' } maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } }}rootProject.buildDir = '../build'subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}"}subprojects { project.evaluationDependsOn(':app')}task clean(type: Delete) { delete rootProject.buildDir}改Flutter的配置文件, 该文件在Flutter装置目录/packages/flutter_tools/gradle/flutter.gradle下载gradle到本地,配置gradle为本地地址(file->setting->gradle) ...

August 23, 2020 · 1 min · jiezi

关于flutter:flutter-路由跳转

单页面路由跳转时留神不要有两个materialapp,因为导航是依赖于这个的,有两个,就会有两个导航 一、两种路由传参办法: DetailScreen跳转的路由组件 间接向路由子组件构造函数传参Navigator.push( context, MaterialPageRoute( builder: (context) => DetailScreen(todo: todos[index]), ), );通过RouteSettings传递参数Navigator.push( context, MaterialPageRoute( builder: (context) => DetailScreen(), settings: RouteSettings( arguments: todos[index], ), ), );二、定义路由:1、在 MaterialApp 中增加属性: initialRoute 和 routes 来定义咱们的路由new MaterialApp( initialRoute: '/', routes: { '/': (context) => TodosScreen(todos: todos), '/detail': (context) => DetailScreen(), }, title: 'ssss',);但要留神的是:当应用 initialRoute 时,须要确保你没有同时定义 home 属性。 2、 给特定的 route 传参:1) 定义须要传递的参数 class ScreenArguments { final String title; final String message; ScreenArguments(this.title, this.message);}2) 创立组件来获取参数 ...

August 21, 2020 · 1 min · jiezi

关于flutter:Flutter-Notes-|-记录基于-macOS-上使用-Flutter-过程中遇到的一些问题

点滴积攒,追随鸡老大~前言每当接触一个新货色,总是会遇到一些想喷人的问题,尽管在前期回过头想想,好简略,当初怎么就掉坑出不来了呢? 正好公司最近来个新我的项目,从 Flutter 进去到当初始终处于偷窥状态,恰好逢此机会,Flutter 搞起来~ 记录本人 Flutter 应用过程遇到的一些问题,心愿能够帮忙和我一样刚入坑的小伙伴~ 缓缓积攒吧~ 问题收集千里之行;始于足下,一起变得更好~ 1. Waiting for another flutter command to release the startup lock...iTerm 中键入如下内容: killall -9 dart2. Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'.FAILURE: Build failed with an exception.* What went wrong:Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'.> Could not resolve all task dependencies for configuration ':app:debugCompileClasspath'. > Could not resolve io.flutter:flutter_embedding_debug:1.0.0-540786dd51f112885a89792d678296b95e6622e5. Required by: project :app > Skipped due to earlier error > Skipped due to earlier error > Skipped due to earlier error > Could not resolve io.flutter:arm64_v8a_debug:1.0.0-540786dd51f112885a89792d678296b95e6622e5. Required by: project :app > Skipped due to earlier error > Skipped due to earlier error > Skipped due to earlier error > Could not resolve io.flutter:x86_debug:1.0.0-540786dd51f112885a89792d678296b95e6622e5. Required by: project :app > Skipped due to earlier error > Skipped due to earlier error > Skipped due to earlier error > Could not resolve io.flutter:x86_64_debug:1.0.0-540786dd51f112885a89792d678296b95e6622e5. Required by: project :app > Skipped due to earlier error > Skipped due to earlier error > Skipped due to earlier error* Try:Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.* Get more help at https://help.gradle.orgBUILD FAILED in 2m 9sException: Gradle task assembleDebug failed with exit code 1掘友很贴心的指导我是因为依赖没有下载下来导致的。 ...

August 21, 2020 · 4 min · jiezi

关于flutter:Flutter-如何创建炫酷粒子时钟效果

本文首发于公众号:技术最TOP周末发表了一篇文章《这个我的项目也太屌了吧》,给大家举荐了一个炫酷的Flutter粒子时钟我的项目,不过没有将具体实现思路和代码,所幸,作者本人写了一篇博客将这个我的项目的背景、实现思路、和所遇到的问题,我感觉对十分有用,因而翻译进去,整顿给大家!原文题目《我是如何创立粒子时钟,并博得了#FlutterClock挑战的》。 背景Google在2019年11月18日发动了The Flutter Clock Challenge挑战流动,内容很简略:应用Flutter UI工具包设计时钟。Google专家小组将依据四个次要规范对参赛作品进行评判:视觉美感,创意新颖性,代码品质和整体执行力。 在这之前,我只应用过Flutter一两次,这对于我来说是一个潜在的机会。 最后的想法挑战开始了大概两周后,我才有了一些想法,但还没有编写任何代码,解决此类问题时,我通常的办法是首先寻找现有的解决方案来找灵感。但这次不行。相同,我在Figma上新建了一个文档,并列出了一些想法。它们都是非常简单数字时钟设计和艰涩的单色组合。 很快地,我就对这个设计感到厌倦了,所以我敞开了Figma,就去下载了Flutter Clock GitHub(https://github.com/flutter/fl...。 这个库蕴含了2个我的项目,一个是基于模仿时钟的演示,另一个是基于数字时钟的演示,我在Figma上设计都是数字的,所以自然而然地,我启动了根本的数字时钟我的项目。再次不足灵感,在示例我的项目的帮忙下,我搁置了挑战,开始去做其余事儿。 几天之后,在一次晨跑中,我又开始认真的思考这个挑战,一个一般的成年人每天看几次手表?对我来说,让时钟变得乏味起来是真正的挑战。是否能够使“报工夫”成为主动体验?比方:即便您对工夫不感兴趣,看着手表也很乏味。这不仅须要视觉上令人惊叹的设计或新鲜的动画计划。 1、如果每次您看钟时都有不同的外观会怎么?2、咱们是否激发好奇心,使您渴望下一次设计迭代?或者,当您喜爱的设计永恒隐没时,您会感到惆怅吗?3、咱们是否能够将背景形态、色彩、动画随机扭转以使它:a. 看起来很酷,b. 足够满足1和2的随机性,c. 不会扩散你看工夫的注意力?我以前从未实现过任何艺术,或者基本没有做过Flutter,所以我着手建造这样的时钟。 粒子与随机性第一次迭代只是一个时钟。如上所述,我从示例数字时钟我的项目开始,而不是从头开始。创立的第一个Widget是一个CustomPainter,仅绘制了一个圆圈。很不错,然而从久远来看不是很乏味。 随机性减少了,从色彩开始,而后确定地位和大小。所有逻辑依然在单个CustomPainter的paint()办法中,这简直使动画变得不可能,因而须要将一堆逻辑重形成一个简略的粒子系统。我看了Flutter Vignettes我的项目,以寻求启发。 https://flutter.gskinner.com/ 这时候,制作模仿粒子时钟的想法变得更加显著了。 将粒子变成模仿时钟提出想法后,我要做的就是编写代码以实现所有指标。数学局部破费了我最多的工夫才最终实现,大多是我多年以前学过的数学,不过好多我都遗记了,角度,弧度,PI和相似的货色,网上又许多解决方案,然而你将不得不做一些批改以适应您的用例。 以下是获取时针弧度的办法: /// Gets the radians of the hour hand.double _getHourRadians() => (time.hour * pi / 6) + (time.minute * pi / (6 * 60)) + (time.second * pi / (360 * 60));我在计算中包含了time.minute和time.second,以使时针在数小时之间平滑地动画。 而后,从弧度取得2D静止矢量就很简略了。 // Particle movement vector.p.vx = sin(-angle);p.vy = cos(-angle);当初,p.vx和p.vy领有 无关粒子在每个动画滴答声中应该挪动多远的信息,同时放弃在时针的角度里。 ...

August 18, 2020 · 2 min · jiezi

关于flutter:flutter-布局

Flutter布局布局步骤抉择用来包容组件的布局组件,比方Center、Container、Row、Column等 居中显示 抉择 Center多个组件放在一行 抉择 Row多个组件放在一列 抉择 Column增加各种盒子款式 抉择 Container创立用来包容可见内容的组件,比方 Text、Image、Icon 等 文本 Text图片 Image图标 Icon将可见组件增加到布局组件里,通过传递给其余属性 child 或 children 如果包容单个组件 例如 Center、Container, 抉择 child如果包容多个组件 例如 Row、Column, 抉择 children将布局组件增加到页面组件里,个别在其 build 办法里实现程度和垂直布局程度和垂直布局是常见的布局,可别离应用 Row 和 Column 来实现,并且他们是能够相互嵌套的对于 Row 和 Column,能够管制其主轴和穿插轴方向上 子组件的对齐形式应用 Expanded 组件来管制子组件的绝对大小罕用布局组件规范布局组件Container 给组件增加填充、边距、边框、背景色等装璜 只能蕴含一个组件设置背景色彩或图片GridView 可滚动的网格 用于二维列表当内容超过渲染区域时将主动滚动如果须要晓得单元所处的行和列,请应用 Table 或 DataTableListView 可滚动的列表 特定化的 Column,不如Column 可定制性强,但更易使用和反对滚动反对垂直或程度滚动Stack 重叠组件 用来重叠多个组件子组件列表里前面的重叠在后面之上外面的内容无奈滚动超过渲染区域的内容可剪切掉Material 布局组件 (* 须要在 MaterialApp 下应用)Card 将相干的组件放到一个卡片里,该卡片带有圆角和暗影 用来出现一组相干的信息只承受一个子组件,但子组件能够是 Row、Column 这样的承受多个子组件的组件带圆角和暗影内容不能滚动需在 MaterialApp 内应用ListTile 带有题目和副标题的行,首尾能够增加图标 特定化的 Row,蕴含最多三行文字,以及可选的图标可定制性不如 Row,但更易使用需在 MaterialApp 内应用

August 17, 2020 · 1 min · jiezi

关于flutter:flutter-布局

Flutter布局布局步骤抉择用来包容组件的布局组件,比方Center、Container、Row、Column等 居中显示 抉择 Center多个组件放在一行 抉择 Row多个组件放在一列 抉择 Column增加各种盒子款式 抉择 Container创立用来包容可见内容的组件,比方 Text、Image、Icon 等 文本 Text图片 Image图标 Icon将可见组件增加到布局组件里,通过传递给其余属性 child 或 children 如果包容单个组件 例如 Center、Container, 抉择 child如果包容多个组件 例如 Row、Column, 抉择 children将布局组件增加到页面组件里,个别在其 build 办法里实现程度和垂直布局程度和垂直布局是常见的布局,可别离应用 Row 和 Column 来实现,并且他们是能够相互嵌套的对于 Row 和 Column,能够管制其主轴和穿插轴方向上 子组件的对齐形式应用 Expanded 组件来管制子组件的绝对大小罕用布局组件规范布局组件Container 给组件增加填充、边距、边框、背景色等装璜 只能蕴含一个组件设置背景色彩或图片GridView 可滚动的网格 用于二维列表当内容超过渲染区域时将主动滚动如果须要晓得单元所处的行和列,请应用 Table 或 DataTableListView 可滚动的列表 特定化的 Column,不如Column 可定制性强,但更易使用和反对滚动反对垂直或程度滚动Stack 重叠组件 用来重叠多个组件子组件列表里前面的重叠在后面之上外面的内容无奈滚动超过渲染区域的内容可剪切掉Material 布局组件 (* 须要在 MaterialApp 下应用)Card 将相干的组件放到一个卡片里,该卡片带有圆角和暗影 用来出现一组相干的信息只承受一个子组件,但子组件能够是 Row、Column 这样的承受多个子组件的组件带圆角和暗影内容不能滚动需在 MaterialApp 内应用ListTile 带有题目和副标题的行,首尾能够增加图标 特定化的 Row,蕴含最多三行文字,以及可选的图标可定制性不如 Row,但更易使用需在 MaterialApp 内应用

August 17, 2020 · 1 min · jiezi

关于flutter:Flutter-Dio包网络请求抓包解决方案

在Flutter中进行网络申请时,咱们能够应用的库有3个,即Http申请库、HttpClient申请库和Dio申请库(具体介绍请参考:Flutter开发之Http网络申请),应用得最多的就是Dio申请库。因为相比Http申请库和HttpClient申请库,Dio库不仅反对常见的网络申请,还反对Restful API、FormData、拦截器、申请勾销、Cookie治理、文件上传/下载、超时等操作。 不过,默认状况下,Dio进行网络申请时是不反对抓包的,所以如果要进行抓包,就须要对Dio进行申请封装,并编写代理代码。上面是代理的几种写法: 办法一咱们能够间接在Dio外面设置ip以及端口,通过硬编码的形式进行代理,代码如下: (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) { //这一段是解决安卓https抓包的问题 client.badCertificateCallback = (X509Certificate cert, String host, int port) { return Platform.isAndroid; }; client.findProxy = (uri) { return "PROXY 代理ip:代理port"; }; };不过,这种硬编码方式,写得太死,不够灵便,每次更改代理都须要打包。 办法二间接在原生插件获取手代理ip和代理端口,不过Android比拟难,上面是iOS的实现。 //主动获取手机代理 NSDictionary *proxySettings = (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings()); NSArray *proxies = (__bridge NSArray *)(CFNetworkCopyProxiesForURL((__bridge CFURLRef _Nonnull)([NSURL URLWithString:call.arguments]), (__bridge CFDictionaryRef _Nonnull)(proxySettings))); NSString *hostName = proxySettings[@"HTTPSProxy"]; NSString *portName = [NSString stringWithFormat:@"%@",proxySettings[@"HTTPPort"]]; long HTTPEnable = [proxySettings[@"HTTPEnable"] longValue]; if (HTTPEnable==0) { hostName = @""; }办法三除了下面的硬编码方式外,咱们还能够采纳scheme协定的形式传入代理ip和代理端口。此办法的步骤如下:1,注册本人的URL Scheme,例如:scheme://2,定义参数规定,例如:scheme://tiaoshi?host=10.0.206.1633,引入flutter插件:uni_links: ^0.2.04,flutter监听解析参数,并在dio外面设置代理5,应用[草料]https://cli.im生成一个二维码:内容:scheme://tiaoshi?host=10.0.206.1636,应用原生相机扫码进入app就能够抓包 ...

August 17, 2020 · 2 min · jiezi

关于flutter:Flutter-Dio包网络请求抓包解决方案

在Flutter中进行网络申请时,咱们能够应用的库有3个,即Http申请库、HttpClient申请库和Dio申请库(具体介绍请参考:Flutter开发之Http网络申请),应用得最多的就是Dio申请库。因为相比Http申请库和HttpClient申请库,Dio库不仅反对常见的网络申请,还反对Restful API、FormData、拦截器、申请勾销、Cookie治理、文件上传/下载、超时等操作。 不过,默认状况下,Dio进行网络申请时是不反对抓包的,所以如果要进行抓包,就须要对Dio进行申请封装,并编写代理代码。上面是代理的几种写法: 办法一咱们能够间接在Dio外面设置ip以及端口,通过硬编码的形式进行代理,代码如下: (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) { //这一段是解决安卓https抓包的问题 client.badCertificateCallback = (X509Certificate cert, String host, int port) { return Platform.isAndroid; }; client.findProxy = (uri) { return "PROXY 代理ip:代理port"; }; };不过,这种硬编码方式,写得太死,不够灵便,每次更改代理都须要打包。 办法二间接在原生插件获取手代理ip和代理端口,不过Android比拟难,上面是iOS的实现。 //主动获取手机代理 NSDictionary *proxySettings = (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings()); NSArray *proxies = (__bridge NSArray *)(CFNetworkCopyProxiesForURL((__bridge CFURLRef _Nonnull)([NSURL URLWithString:call.arguments]), (__bridge CFDictionaryRef _Nonnull)(proxySettings))); NSString *hostName = proxySettings[@"HTTPSProxy"]; NSString *portName = [NSString stringWithFormat:@"%@",proxySettings[@"HTTPPort"]]; long HTTPEnable = [proxySettings[@"HTTPEnable"] longValue]; if (HTTPEnable==0) { hostName = @""; }办法三除了下面的硬编码方式外,咱们还能够采纳scheme协定的形式传入代理ip和代理端口。此办法的步骤如下:1,注册本人的URL Scheme,例如:scheme://2,定义参数规定,例如:scheme://tiaoshi?host=10.0.206.1633,引入flutter插件:uni_links: ^0.2.04,flutter监听解析参数,并在dio外面设置代理5,应用[草料]https://cli.im生成一个二维码:内容:scheme://tiaoshi?host=10.0.206.1636,应用原生相机扫码进入app就能够抓包 ...

August 17, 2020 · 2 min · jiezi

关于flutter:自绘引擎时代为什么Flutter能突出重围

导语 | Flutter 框架是当下十分热门的跨端解决方案,可能帮忙开发者通过一套代码库高效构建多平台精美利用,反对挪动、Web、桌面等多端开发。但依然有很多产品、设计、甚至开发同学并不理解 Flutter,所以本文将深入浅出和大家聊聊 Flutter 的设计背景、技术特点,以及与其余同类技术之间的比照,心愿与大家一起交换。一、跨平台背景1. 挪动互联网的重要性 如上图所示,与2019年1月相比,寰球应用互联网的人数已减少到45.4亿,增长了7%(2.98亿新用户)。 到2020年1月,寰球有38亿社交媒体用户,与去年同期相比,这个数字增长了9%以上(3.21亿新用户)。 在寰球范畴内,当初有超过51.9亿人应用手机,在过来的一年中,用户数量减少了1.24亿(2.4%)。 当初,一般的互联网用户每天在线破费6个小时43分钟,相当于每个互联网用户每年连接时间超过100天。如果咱们每天须要大概8小时的睡眠,那就意味着醒来的工夫中,有40%以上是通过互联网度过的。 在挪动互联网的浪潮下,开发效率和应用体验能够说是等同重要。然而,应用原生的形式来开发 App,就要求咱们必须针对 iOS 和 Android 这两个平台别离开发。 这样就导致了咱们不仅须要在不同的我的项目间尝试用不同的语言去实现同样的性能,还要承当由此带来的保护工作。如果还要持续向其余平台(比方 Web、Mac 或 Windows)拓展的话,须要付出的工夫和老本将成倍增长。而这,显然是难以承受的。于是,跨平台开发的概念趁势走进了大家的视线。 从实质上讲,跨平台开发是为了减少业务代码的复用率,缩小因为要适配多个平台带来的工作量,从而升高开发成本。 2. 跨平台开发计划的三个时代依据实现形式的不同,业内常见的观点是将支流的跨平台计划划分为三个时代。 (1)Web 容器时代基于 Web 相干技术通过浏览器组件来实现界面及性能,典型的框架包含 Cordova(PhoneGap)、Ionic 和微信小程序。 Web 时代的计划,次要采纳的是原生利用内嵌浏览器控件 WebView 的形式进行 HTML5 页面渲染。 因为采纳了 Web 开发技术,社区和资源十分丰盛,开发效率也很高。然而,一个残缺 HTML5 页面的展现要经验浏览器控件的加载、解析和渲染三大过程,性能耗费要比原生开发减少 N 个数量级。 (2)泛 Web 容器时代采纳类 Web 规范进行开发,但在运行时把绘制和渲染交由原生零碎接管的技术,代表框架有 React Native、Weex 和快利用,狭义的还包含天猫的 Virtual View 等。 泛 Web 容器时代的解决方案优化了 Web 容器时代的加载、解析和渲染这三大过程,把影响它们独立运行的 Web 规范进行了裁剪,以绝对简略的形式反对了构建挪动端页面必要的 Web 规范(如 Flexbox 等),也保障了便捷的前端开发体验。 ...

August 17, 2020 · 2 min · jiezi

关于flutter:Flutter-混合开发-02-百度地图定位功能-android-篇

本节指标百度地图业务百度组件初始编写定位代码 android 篇 环境$ flutter doctorDoctor summary (to see all details, run flutter doctor -v):[✓] Flutter (Channel stable, 1.20.1, on Mac OS X 10.15.6 19G73, locale zh-Hans-CN)[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)[✓] Xcode - develop for iOS and macOS (Xcode 11.6)[✓] Android Studio (version 4.0)[✓] VS Code (version 1.47.3)视频https://www.bilibili.com/vide... 代码https://github.com/ducafecat/... 能够间接用 ???? v1.0.3 https://github.com/ducafecat/... 注释创立组件的几种形式现成轮子间接用官网仓库搜寻https://pub.dev/flutter/packages https://pub.flutter-io.cn/flu... 可参考的组件代码通过仓库,查找 github 代码仓网站、客服索取代码参考官网集成文档编写组件官网文档http://lbsyun.baidu.com/index... ...

August 13, 2020 · 13 min · jiezi

关于flutter:定位Flutter内存问题很难么

简介: flutter内存透露定位 作者:闲鱼技术-三莅 内存水位升高导致的稳定性问题重大影响app用户体验,所以开发者们十分关注Flutter的内存体现。随着Flutter业务越来越多,闲鱼也面临着oom导致的crash率晋升的问题,上面咱们联合我的项目中理论遇到的内存问题和解决思路跟大家分享下flutter内存优化的教训。 本文分为三个局部 理解Dart VM内存调配及销毁原理通过Observatory工具剖析内存透露,缩小不必要的内存占用Flutter中常见内存透露场景有哪些,如何在业务利用中防止踩坑Dart VM内存调配及销毁原理DartVM的垃圾回收机制分两个阶段,新生代(New Generation)和老年代(Old Generation)。 新生代用来存储生命周期较短的对象,由两个内存空间组成,Active内存空间用来调配新对象,inActive内存空间用来作为备用空间,DartVM的内存调配策略非常简单,创建对象时只须要在现有堆上挪动指针,内存增长始终是线形的,省去了查找可用内存段的过程。每个Isolate有本人独立的Heap,相互之间无奈共享内存,这样能够实现无锁的疾速调配。 一旦Active的内存空间被填满,垃圾回收器会从根对象开始遍历查看查看所有对象的援用状态,没有被援用的对象标记为dead状态,非dead状态的对象在下次内存回收事件中会被复制到inActive内存空间,革除Active内存空间,最初Active和inActive内存空间状态调换。 当对象达到肯定的生命周期,会被移到老年代内存空间治理,这种垃圾收集策略有两个阶段,1. 首先遍历对象图,并标记仍在应用的对象。2. 扫描整个内存,并回收任何未标记的对象,而后革除所有标记。这种内存清理的频率较低,并且在扫描回收阶段须要暂停Dart runtime,回收老本较高,比拟适宜Flutter中大量StatelessWidget的模式(大部分都寄存在新生代)。 另外,当engine检测到利用是idle状态并且没有用户交互的时候会发送告诉垃圾收集器开始清理内存,最小化对性能的影响。这些策略让Dart的内存调配和回收都十分高效。 Android和IOS中都存在强援用弱援用的概念,区别在于一个对象具备强/弱援用,零碎会不会开释该对象占用的内存空间,Dart并没有弱援用的概念,然而有个特例Expando ,它会以弱援用的形式持有 key,相当于一个弱利用的map,感兴趣的能够理解下。 Dart VM借鉴了很多JVM的思路,Dart中产生内存泄露的形式也和Java相似,Java中很多排查内存泄露的思路和避免内存泄露的办法应该也能够借鉴过去。Android能够通过Profile和LeakMemory等工具检测app中的内存透露,Flutter如何检测呢?能够应用Observatory或者DevTools。 通过Observatory剖析内存透露Observatory是官网提供的调试工具,通过dart vm获取运行时信息,通过它咱们能够剖析一系列性能相干数据,例如app耗时统计,代码覆盖率等,这里咱们重点介绍内存相干的调试工具。(DevTools也能够用来调试剖析性能数据,它是在Observatory层做了一层封装,然而目前还是beta版本)。 上面咱们用闲鱼中的理论例子介绍下如何应用Observatory查看看Dart VM内存应用状况,留神所有对于性能的剖析要在Profile模式下进行。 关上Observatory URL的Web页面。运行app,在控制台中查找相似输入日志listening on ws://127.0.0.1:64673/hXsWR_ZOsGk=/ws, 示意以后连贯的VM地址,输出到浏览器就能够看到Observatory主界面,显示了dart vm一些根底信息,具体应用办法能够参考 官网文档,这里不再详细描述,咱们重点关注右下角的allocation profile选项。 点击右下角allocation profile选项后,操作app进入想要剖析的Flutter页操作,退出该页面,点击页面右上角 GC按钮触发手动GC,查看Class,发现有局部DX Class内存占用,这类class本应该只有在指标剖析页会呈现,退出指标剖析也后手动GC会被齐全开释,然而这里任然能看到相干内存占用,阐明产生了内存透露。 点击对应class查看具体利用实例,点击对应实例进入查看援用门路,就能找到没有导致开释的援用变量,联合业务代码具体分析,就能发现透露的源头。 这里有一点须要留神,Observatory显示的Dart VM占用的内存信息要远远小于Android Profile/Xcode检测出的内存大小,因为存在局部只有零碎工具能检测出的内存区块,例如一些齐全不依赖于DartVM的skia对象,并且layer在engine中创立时并不能明确晓得大小,所以采纳虚构近似值代替。 //engine/lib/ui/painting/engine_layer.cc...size_t EngineLayer::GetAllocationSize() { // Provide an approximation of the total memory impact of this object to the // Dart GC. The ContainerLayer may hold references to a tree of other layers, // which in turn may contain Skia objects. return 3000;};上面咱们总结了几种常见内存透露的场景,在Java中都能够一一对应找到相似的场景,大家在业务开发中留神防止 ...

August 13, 2020 · 1 min · jiezi

关于flutter:构建复杂应用的神器FBroadcast

FWidget 用心提供粗劣的组件,助您构建精美的利用。 FWidget 始终致力于为开发者们精心打造易于构建精美利用的 Widget。 迄今为止,FWidget 曾经收到了来自开发者们的 1215 个 Star,感激开发者们的反对,这对 FWidget 来说至关重要。 明天,FWidget 为开发者们带来了一个全新的组件 FBroadcast,以帮忙开发者们可能更轻松的构建更为简单精美的利用。 例如,在 FWidget 的官方网站 https://fwidget.cn 中,通过 FBroadcast 很轻松的就实现了老本极低的,且易于保护的全局实时语言切换。它非常简略无效和明确! ✨ 个性来看看 FBroadcast 为开发者提供了那些不堪设想的能力反对: 反对发送和接管指定类型的音讯音讯反对携带任意类型数据包提供环境注册,一行代码即可移除环境内所有接收者不堪设想的粘性播送双向通信反对易于构建简略明确的部分和全局状态治理 ???? 传送区???? 【传送门:FBroadcast Github 主页】???? 【传送门:FBroadcast 文档】???? 献给开发者的 FBroadcastFBroadcast 是一套高效灵便的广播系统,能够帮忙开发者轻松、有序的构建具备极具复杂性的关联交互和状态变动的精美利用。 FBroadcast 将为构建简单的精美利用带来那些不言而喻的扭转呢? Widget/模块间的齐全解耦 通过 FBroadcast 高效的广播系统,开发者能够轻易的实现Widget/模块的解耦。在利用构建的时候,常常须要 Widget/模块A、B、C、.. 之间依据交互操作相互变更状态或数据,开发者们不得不为此让各个Widget/模块相互依赖或者为它们建设对立的状态治理,这能解决问题,但这让构建变得麻烦,也让变更变得难以进行。 FBroadcast 通过建设起简略、无效、明确广播系统,使得在任意Widget/模块中任意时刻/地位的扭转可能被动收回播送,而须要依据这些变更作出响应或更新视图的Widget/模块只须要注册相应的信息接收器,就能够在变更产生时,接管到音讯,作出响应。这使得关联模块间不再须要相互依赖,或是为它们设计建设对立的状态管理器。 非常简略,轻量,和易于变更。当一个Widget/模块不在须要依据另一个Widget/模块的变更而更新时,只需移除其中的接收器即可,而不必为此而大改依赖关系或是状态管理器。 简略、灵便、明确、易治理 FBroadcast 为开发者提供了能够在任意时刻发送播送,和注册/移除接收器的能力,毫无束缚和灵便。 播送和接收器之间通过明确的类型(字符串)来相互确认身份,指定类型的播送,只能被指定类型的接收器接管。 FBroadcast 提供了环境注册反对,开发者能够在环境解构时,通过 [unregister()] 函数一次性移除环境中的所有类型接收器,而无需记忆和关怀到底须要移除那些接收器。例如,开发者能够在 Widget 的 dispose() 中,将注册在该 Widget 中的所有接收器一次性全副移除。 借助古代IDEA的能力,开发者能够为广播系统建设一张(或多张)对立的播送类型索引表,通过IDEA的援用索引,开发者能够轻松的、高深莫测的看到该类型的播送在那些中央被发送过,在那些中央注册了接收器,非常易于治理和保护。而应用字符串来作为类型标识,使得开发者能够将不同类型的播送含意形容的足够清晰明确。 ...

August 12, 2020 · 6 min · jiezi

关于flutter:flutter有一些问题的解决

Flutter Text 文字下有黄色下划线https://www.jianshu.com/p/1f0a29cddba1

August 10, 2020 · 1 min · jiezi

关于flutter:Flutter-120正式版发布带来多个新特性

前两天,Google公布了Flutter 1.20 的正式版,这是继Flutter 1.17 版本之后又一重要的版本。始终以来,Google都在致力于 Flutter 的疾速,好看,高效和凋谢地四个方面来一直的开发产品,围绕这四个方面,此次版本带来了性能晋升、挪动端主动补全、新的性能小部件等泛滥个性。 为了使开发者可能构建更加精美的 Flutter 应用程序,1.20 版本提供了多项 UI 加强性能,包含期待已久的: 主动补全反对;对 Widget 进行分层以反对平移和缩放的新形式;鼠标光标反对;对旧版本的 Material Widget(例如工夫和日期选择器),同时也为台式机与挪动端 Flutter 利用中的 About 框带来全新的响应式许可页面的更新。同时,为了保障可能持续晋升开发者的工作效率,咱们还面向 Visual Studio Code 对 Flutter 进行扩大更新,旨在将 Dart DevTools 间接纳入 IDE 之内、在挪动文件时自动更新导入语句、并提供一组新的元数据供您进一步构建本人的工具。 Flutter 凭借着明确的开放性与沉闷的社区奉献放弃着旺盛的生机,此次公布的新版本中蕴含来自寰球 359 位贡献者(其中 270 位贡献者来自 Flutter 社区)提交的 3029 条合并 PR,外加 5485 项已敞开问题。这也是 Flutter 我的项目倒退至今,涵盖贡献者最多的一次更新。 社区贡献者 CareF 提交 28 项 PR,AyushBherwani1998 提交了 26 项 PR、其中包含 10 项用于 Google Summer of Code 我的项目的 Flutter 样本,a14n 提交了 13 项 PR、其中大部分与 Flutter 的登陆服务平安相干,在这里咱们向各位贡献者致以诚挚的谢意!这是 Flutter release 版本中蕴含的最多社区奉献,特地是向这些社区贡献者表示感谢! ...

August 7, 2020 · 2 min · jiezi

关于flutter:Flutter开发之Dart-DevTools

Dart DevTools 简介Flutter是Google开源的一个跨平台 UI 工具包,能够帮忙开发者通过一套代码库高效构建多平台精美利用,反对挪动、Web、桌面和嵌入式平台。同时,它也是Google将来的 Google Fuchsia 利用构建的次要形式。目前,Flutter齐全开源、收费,领有宽松的开源协定,适宜商业我的项目。 应用Flutter开发跨平台利用时,常常须要用到一个开发者工具,即Dart DevTools,Dart DevTools是一套用于Dart和Flutter利用开发的性能和调试工具,能够用它来检测和剖析利用的性能,以及用它来调试利用日志和进行内存剖析等。 目前,Dart DevTools反对的性能有如下一些: 检查和剖析应用程序的UI布局和状态。诊断利用的UI 性能问题。检测和剖析应用程序的CPU应用状况。剖析应用程序的网络应用状况。Flutter或Dart应用程序的源代码级调试。调试Flutter或Dart应用程序的内存应用状况和剖析内存问题。查看运行的Flutter或Dart应用程序的个别日志和诊断信息。装置DevTools应用DevTools之前须要先装置DevTools插件,如果还没有装置,能够先装置它。 Android Studio默认状况下,只有装置了Flutter开发环境,根本就曾经装置了DevTools工具,装置之后运行我的项目会在DevTools工具栏看到如下图所示的工具集。应用DevTools进行利用程序调试时,能够先在Run视图中抉择Open DevTools工具栏,而后在Debug视图中抉择Open DevTools工具栏进行操作,如下图所示。具体的调试和剖析技巧会在前面讲到。 VS Code如果应用的是VS Code集成开发环境,那么须要先在VS Code中装置Dart DevTools插件,顺次抉择【View】→【Command Palette…】关上搜寻菜单。在菜单中输出install,并抉择Extensions:Install Extension,而后在输入框中输出Dart DevTools点击装置即可,如下图所示。第一次启动DevTools插件时,会看到下图所示的降级提醒。当点击【Open】按钮时就会在浏览器中启动并主动连贯调试窗口,如下图所示。 DevTools应用技巧最近,Google对 Dart DevTools 进行了降级,并公布了最新的版本,对 Dart 和 Flutter 代码调试和性能剖析进行了优化。Flutter官网抉择以 Web 利用的模式交付 DevTools,这是因为能够轻松地将其集成到咱们所有指标平台和 IDE 的现有工具体验中,以 Web 状态构建 DevTools 也可能带来更好的用户体验。 目前,DevTools是一套在浏览器中运行的独立工具,这些工具提供了额定的监测等性能,而这些性能是无奈在 IDE 中显示的,之所以这样设计,是因为思考到跨平台调试的须要。最新版本的 DevTools 是应用 Flutter 编写的 ,而之前用的是 Dart 编写的,因而在最新的版本中,改良界面并增加全新的性能。应用最新版的DevTools开启利用调试,界面如下图所示。 Flutter Inspector在下面的调试视图中,第一个标签是 【Flutter Inspector】,这是一款用于可视化和浏览 Flutter Widget 树的工具。您能够抉择正在运行的利用中的 Widget,而后加快所有动画,查看文本基线等等,如下图所示。Layout Explorer 是一项新增性能,在 Flutter Inspector 中位于 Details Tree 视图旁边。应用 Layout Explorer,您能够查看 Flutter 的柔性布局 (flex layout) 模型。例如,当您不确定为什么一排 widget 没有按您预期的形式显示时,或者为什么会呈现 "RenderFlex 溢出了 42 个像素" 这样的谬误时,这个性能兴许能帮上大忙。在 Flutter Inspector的左边,会发现三个专门用于性能剖析的标签页: Timeline (工夫线视图)、Memory (内存视图) 和 Performance (性能视图)。当然,Flutter Inspector的性能还有很多,能够自行查看Flutter Inspector官网材料的介绍。 ...

August 6, 2020 · 1 min · jiezi

关于flutter:浅析-Flutter-与-iOS-的视图桥梁

PlatformView 提供了在 Flutter 的 Widget 层级中嵌入原生视图(iOS/Android等), PlatformView 在用来形容 iOS 平台是视图用的是 UIKitView,Android 平台的视图是 AndoirdView,本文所有形容都是针对 iOS 平台,按官网的形容该性能还是在公布预览阶段,并且是十分低廉的操作;以下是官网 API 文档原文正文: Embedding UIViews is still in release preview, to enable the preview for an iOS app add a boolean field with the key 'io.flutter.embedded_views_preview' and the value set to 'YES' to the application's Info.plist file. A list of open issued with embedding UIViews is available on Github. Embedding iOS views is an expensive operation and should be avoided when a Flutter equivalent is possible.场景每个技术点的呈现必然有它的价值所在,所以即使 PlatfromView 目前存在一些问题,并且 Flutter 自身就是一个 UI 框架,一些业务场景下只能依赖于它实现,例如:地图、原生广告、WebView等等;所以 Flutter 开发者还是得点亮 PlatformView 技能树; ...

August 6, 2020 · 5 min · jiezi

关于flutter:浅析-Flutter-与-iOS-的视图桥梁

PlatformView 提供了在 Flutter 的 Widget 层级中嵌入原生视图(iOS/Android等), PlatformView 在用来形容 iOS 平台是视图用的是 UIKitView,Android 平台的视图是 AndoirdView,本文所有形容都是针对 iOS 平台,按官网的形容该性能还是在公布预览阶段,并且是十分低廉的操作;以下是官网 API 文档原文正文: Embedding UIViews is still in release preview, to enable the preview for an iOS app add a boolean field with the key 'io.flutter.embedded_views_preview' and the value set to 'YES' to the application's Info.plist file. A list of open issued with embedding UIViews is available on Github. Embedding iOS views is an expensive operation and should be avoided when a Flutter equivalent is possible.场景每个技术点的呈现必然有它的价值所在,所以即使 PlatfromView 目前存在一些问题,并且 Flutter 自身就是一个 UI 框架,一些业务场景下只能依赖于它实现,例如:地图、原生广告、WebView等等;所以 Flutter 开发者还是得点亮 PlatformView 技能树; ...

August 6, 2020 · 5 min · jiezi

关于flutter:Flutter-Fluro路由库的页面切换动画效果

fluro的页面切换函数 Router.navigateTo 反对11种不同成果的切换动画,反对延时设置和自定义切换成果,上面将会对所有的成果展现进去,不便当前能够依据理论需要进行抉择。 切换成果分类fluro内置的切换动画能够分为3类: 各平台原生成果非原生成果自定义成果Router.navigateTo( context path transition transitionBuilder transitionDuration)上一篇文章,曾经介绍过Flutter的路由治理和Fluro的应用了,咱们曾经晓得 Router.navigateTo 函数。只有批改transition则能够实现不同的切换成果,transitionBuilder用于自定义切换成果,transitionDuration为切换动画所需工夫的设置。 1. 各平台原生成果这里的平台只针对android和ios,在上一篇文章中曾经介绍过,应用零碎默认的路由管理系统进行页面跳转的时候,flutter会依据所在平台执行不同的切换成果,在安卓中是从下到上的渐显,而ios是从右向左的滑入。 在fluro中,原生成果分为三种,每种类型都成对呈现: 随平台应用成果:TransitionType.native 和 TransitionType.nativeModal 应用安卓的成果:TransitionType.material 和 TransitionType.materialFullScreenDialog 应用ios的成果:TransitionType.cupertino 和 TransitionType.cupertinoFullScreenDialog 每个成果都成对呈现,因为Flutter中的原生路由切换成果分为非全屏和全屏。 在Material和Cupertino中,全屏成果的AppBar左侧是敞开按钮而不是后退按钮。 在iOS上,全屏成果不再是向左滑入,变成了从下往上移入,而且不能用向右滑动的手势敞开页面了。 须要留神的是,以上6中原生的切换成果并不反对transitionDuration自定义切换工夫,均采纳和原生统一的成果。 2. 非原生成果fluro也内置了4种常见的成果,这4个成果都是反对transitionDuration自定义切换工夫。 渐显:TransitionType.fadeIn从左向右进入:TransitionType.inFromLeft 从右向左进入:TransitionType.inFromRight 从下向上进入:TransitionType.inFromBottom 3. 自定义成果除了以上10种成果外,还有一个非凡的自定义成果,TransitionType.custom。 它必须搭配transitionBuilder参数。 自定义成果也反对应用 transitionDuration 自定义切换工夫。 上面就是一个自定义的渐隐渐显成果示例: ...Router.navigateTo( context, path, transition: TransitionType.custom, transitionBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) { return FadeTransition( opacity: CurvedAnimation( parent: animation, curve: Curves.linear, ), child: child ); }, transitionDuration: Duration(seconds: 1), // 须要1s切换);... ...

August 6, 2020 · 1 min · jiezi

关于flutter:flutter安装过程中的问题

X Android license status unknown.

August 3, 2020 · 1 min · jiezi

关于flutter:何谓高质感FWidget

FWidget 用心提供粗劣的组件,助您构建精美的利用。最近,咱们对 FWidget 进行了一次 超前 的降级 ???? FWidget 是由【阿里巴巴-飞猪-FliggyMobile技术团队】 开发的系列组件库, FWidget 始终奉行 "用心提供粗劣的组件,助您构建精美的利用" 的信念,力求为开发者们提供一套粗劣易用的组件库,帮忙开发者们更易构建出精彩绝伦的利用。 迄今为止, FWidget 曾经为开发者们打造了一批粗劣的组件。目前, FWidget 累计向社区凋谢公布了其中的 10 余个组件,取得了来自社区开发者们投出的超过 1130 个 Star。开发者们给予的认可和反对,也是 FWidget 持续用心提供更多新组件的重要能源。 最近, FWidget 为开发者们带来了一次前所未有的 超前 降级,赋能予开发者们构建更惊艳的,高质感的利用的能力。 ???? 那么,何谓高质感?开发者,请定目细看,来自全新降级的 FButton 和 FSuper 所构建进去的高质感视效。 #FButton 通过对 光源、暗影、明暗变动 的细腻解决, FWidget 为开发者们打造出了极具艺术感的高质感组件。 正如你所见,这些粗疏的光影成果解决,可能使得界面元素 "脱离" 界面。呈现出真切的 突出,陷入 视效,带来前所未有的视觉冲击感。 #FSuper 于此同时, FWidget 所提供的不是简略的固定光源下的光影成果。开发者能够依据爱好或是须要,自在设定光源方向,以充沛出现代码家们的艺术设计。 是的, FWidget 可能依据不同的光源方向,动静的调整适宜的暗影、明暗成果,以完满出现真切的视效。 ???? 这很难吗?不! 对于开发者而言, FWidget 所提供的这种惊艳的表现力,实现起来放弃了一贯的简洁。甚至,开发者只须要增加一个属性,就能够立刻构建出一个的高质感界面元素。 在 FButton 中: ...

August 3, 2020 · 2 min · jiezi

关于flutter:Flutter状态管理-BLoCScopedModel和Provider的对比

Flutter的运行也是基于状态的变动触发绘制的。所以,Flutter开发个别是离不开这个主题的。 最常见的就是应用StatefulWidget和setState。然而,这样的用法无奈满足日渐增长的页面数量和暗藏在这些页面里的越来越简单的业务逻辑。于是,各路大神开发除了与之配套的模式和响应的库来简化App的状态治理。其中最显著的几个模式别离是BLoC、ScopedModel和Provider。上面咱们就一一的剖析和比照他们的异同。以此来帮忙开发者抉择适合的模式和库。 示例本文中所应用的示例是Flutter Sample的Provider shopper, 这里能够看到。运行成果是这样的: 运行的成果是齐全一样的,只是在Provider的局部还是少许做了一点批改。本例应用的代码是为了表明Provider的一些根底用法。同一套代码适配到不同的模式下,才更有比照的价值。实现同一个性能,在不同的模式下该如何操作,不同点、共同点都特地显著。 笔者也是初学者,对各种模式的了解不免有不到位的中央。欢送各位读者指出谬误,或者一起探讨。BLoC这是一个模式,也有对应库。它最显著的特点就是有“流”。所以,要应用BLoC就要学会流。 说道流就会有很多的读者想到响应式编程。没错这的确是响应式编程的概念,不过Dart有本人的一套流的实现。咱们来具体关注一下Dart的实现。这里补充一点,如果你想用ReactiveX的一套实现也是没有问题的。 应用流控制器解决数据Dart提供了一个叫做StreamController的类来治理流(Stream)。流控制器(StreamController)会放出一个两个成员来共开发者应用,别离能够读取流外面的值,或者向流增加数据。开发者能够通过StreamController#Stream实例来读取数据,通过StreamController#Sink`实例来增加数据。 在一个ViewModel里如何应用流控制器: /// 这里去掉了不必要的代码class CartBloc extends BaseBloc { // 实例化流控制器 final _controller = StreamController<Item>.broadcast(); // Stream间接作为public属性裸露进来 Stream<Item> get stream => _controller.stream; void addItem(Item item) { // 应用Sink增加数据 _controller.sink.add(item); } @override void dispose() { // 敞开流控制器,开释资源 _controller.close(); }}在这个类外面,首先示例话了一个流控制器:final _controller = StreamController<Item>.broadcast();。申明了一个 应用了一个stream getter:Stream<Item> get stream => _controller.stream;把流裸露给里面应用。同时有一个办法addItem用来接管新增加的数据,并在其外部实现里应用_controller.sink.add(item)增加数据。 在示例化流控制器的时候,是这样做的:StreamController<Item>.broadcast()。应用到了broadcast()。这里也能够是stream()。然而stream仅反对一个监听者,如果存在多个监听者的时候就会抛异样了。所以,个别都是应用stream()取得流控制器实例,如果有多个监听者的时候再应用broadcast()。简略说,就是始终用stream()直到呈现多个监听者报错的时候换boradcast()。 stream和sink基本上能够了解为一个管子的中间。应用sink给这个管子假数据,数据流过这个管子之后能够通过stream拿到数据。 应用StreamBuilder显示流数据流控制器解决好数据之后,就要在界面上把数据展示进去。 Flutter提供了StreamBuilder来展现流的数据。代码如下: Widget build(BuildContext context) { return Scaffold( // StreamBuilder,须要一个stream,和一个builder body: StreamBuilder<CatalogModel>( stream: BlocProvider.of<CatalogBloc>(context).stream, builder: (context, snapshot) { // 数据能够从snapshot.data拿到 CatalogModel catalog = snapshot.data; return CustomScrollView( // 此处省略 ); })); }应用StreamBuilder只须要给它一个Stream和一个Builder办法即可。在获取每个传入给StreamBuilder的Stream的时候还有更加简化的办法。 ...

August 2, 2020 · 5 min · jiezi

关于flutter:Flutter状态管理-BLoCScopedModel和Provider的对比

Flutter的运行也是基于状态的变动触发绘制的。所以,Flutter开发个别是离不开这个主题的。 最常见的就是应用StatefulWidget和setState。然而,这样的用法无奈满足日渐增长的页面数量和暗藏在这些页面里的越来越简单的业务逻辑。于是,各路大神开发除了与之配套的模式和响应的库来简化App的状态治理。其中最显著的几个模式别离是BLoC、ScopedModel和Provider。上面咱们就一一的剖析和比照他们的异同。以此来帮忙开发者抉择适合的模式和库。 示例本文中所应用的示例是Flutter Sample的Provider shopper, 这里能够看到。运行成果是这样的: 运行的成果是齐全一样的,只是在Provider的局部还是少许做了一点批改。本例应用的代码是为了表明Provider的一些根底用法。同一套代码适配到不同的模式下,才更有比照的价值。实现同一个性能,在不同的模式下该如何操作,不同点、共同点都特地显著。 笔者也是初学者,对各种模式的了解不免有不到位的中央。欢送各位读者指出谬误,或者一起探讨。BLoC这是一个模式,也有对应库。它最显著的特点就是有“流”。所以,要应用BLoC就要学会流。 说道流就会有很多的读者想到响应式编程。没错这的确是响应式编程的概念,不过Dart有本人的一套流的实现。咱们来具体关注一下Dart的实现。这里补充一点,如果你想用ReactiveX的一套实现也是没有问题的。 应用流控制器解决数据Dart提供了一个叫做StreamController的类来治理流(Stream)。流控制器(StreamController)会放出一个两个成员来共开发者应用,别离能够读取流外面的值,或者向流增加数据。开发者能够通过StreamController#Stream实例来读取数据,通过StreamController#Sink`实例来增加数据。 在一个ViewModel里如何应用流控制器: /// 这里去掉了不必要的代码class CartBloc extends BaseBloc { // 实例化流控制器 final _controller = StreamController<Item>.broadcast(); // Stream间接作为public属性裸露进来 Stream<Item> get stream => _controller.stream; void addItem(Item item) { // 应用Sink增加数据 _controller.sink.add(item); } @override void dispose() { // 敞开流控制器,开释资源 _controller.close(); }}在这个类外面,首先示例话了一个流控制器:final _controller = StreamController<Item>.broadcast();。申明了一个 应用了一个stream getter:Stream<Item> get stream => _controller.stream;把流裸露给里面应用。同时有一个办法addItem用来接管新增加的数据,并在其外部实现里应用_controller.sink.add(item)增加数据。 在示例化流控制器的时候,是这样做的:StreamController<Item>.broadcast()。应用到了broadcast()。这里也能够是stream()。然而stream仅反对一个监听者,如果存在多个监听者的时候就会抛异样了。所以,个别都是应用stream()取得流控制器实例,如果有多个监听者的时候再应用broadcast()。简略说,就是始终用stream()直到呈现多个监听者报错的时候换boradcast()。 stream和sink基本上能够了解为一个管子的中间。应用sink给这个管子假数据,数据流过这个管子之后能够通过stream拿到数据。 应用StreamBuilder显示流数据流控制器解决好数据之后,就要在界面上把数据展示进去。 Flutter提供了StreamBuilder来展现流的数据。代码如下: Widget build(BuildContext context) { return Scaffold( // StreamBuilder,须要一个stream,和一个builder body: StreamBuilder<CatalogModel>( stream: BlocProvider.of<CatalogBloc>(context).stream, builder: (context, snapshot) { // 数据能够从snapshot.data拿到 CatalogModel catalog = snapshot.data; return CustomScrollView( // 此处省略 ); })); }应用StreamBuilder只须要给它一个Stream和一个Builder办法即可。在获取每个传入给StreamBuilder的Stream的时候还有更加简化的办法。 ...

August 2, 2020 · 5 min · jiezi

关于flutter:Flutter状态管理-BLoCScopedModel和Provider的对比

Flutter的运行也是基于状态的变动触发绘制的。所以,Flutter开发个别是离不开这个主题的。 最常见的就是应用StatefulWidget和setState。然而,这样的用法无奈满足日渐增长的页面数量和暗藏在这些页面里的越来越简单的业务逻辑。于是,各路大神开发除了与之配套的模式和响应的库来简化App的状态治理。其中最显著的几个模式别离是BLoC、ScopedModel和Provider。上面咱们就一一的剖析和比照他们的异同。以此来帮忙开发者抉择适合的模式和库。 示例本文中所应用的示例是Flutter Sample的Provider shopper, 这里能够看到。运行成果是这样的: 运行的成果是齐全一样的,只是在Provider的局部还是少许做了一点批改。本例应用的代码是为了表明Provider的一些根底用法。同一套代码适配到不同的模式下,才更有比照的价值。实现同一个性能,在不同的模式下该如何操作,不同点、共同点都特地显著。 笔者也是初学者,对各种模式的了解不免有不到位的中央。欢送各位读者指出谬误,或者一起探讨。BLoC这是一个模式,也有对应库。它最显著的特点就是有“流”。所以,要应用BLoC就要学会流。 说道流就会有很多的读者想到响应式编程。没错这的确是响应式编程的概念,不过Dart有本人的一套流的实现。咱们来具体关注一下Dart的实现。这里补充一点,如果你想用ReactiveX的一套实现也是没有问题的。 应用流控制器解决数据Dart提供了一个叫做StreamController的类来治理流(Stream)。流控制器(StreamController)会放出一个两个成员来共开发者应用,别离能够读取流外面的值,或者向流增加数据。开发者能够通过StreamController#Stream实例来读取数据,通过StreamController#Sink`实例来增加数据。 在一个ViewModel里如何应用流控制器: /// 这里去掉了不必要的代码class CartBloc extends BaseBloc { // 实例化流控制器 final _controller = StreamController<Item>.broadcast(); // Stream间接作为public属性裸露进来 Stream<Item> get stream => _controller.stream; void addItem(Item item) { // 应用Sink增加数据 _controller.sink.add(item); } @override void dispose() { // 敞开流控制器,开释资源 _controller.close(); }}在这个类外面,首先示例话了一个流控制器:final _controller = StreamController<Item>.broadcast();。申明了一个 应用了一个stream getter:Stream<Item> get stream => _controller.stream;把流裸露给里面应用。同时有一个办法addItem用来接管新增加的数据,并在其外部实现里应用_controller.sink.add(item)增加数据。 在示例化流控制器的时候,是这样做的:StreamController<Item>.broadcast()。应用到了broadcast()。这里也能够是stream()。然而stream仅反对一个监听者,如果存在多个监听者的时候就会抛异样了。所以,个别都是应用stream()取得流控制器实例,如果有多个监听者的时候再应用broadcast()。简略说,就是始终用stream()直到呈现多个监听者报错的时候换boradcast()。 stream和sink基本上能够了解为一个管子的中间。应用sink给这个管子假数据,数据流过这个管子之后能够通过stream拿到数据。 应用StreamBuilder显示流数据流控制器解决好数据之后,就要在界面上把数据展示进去。 Flutter提供了StreamBuilder来展现流的数据。代码如下: Widget build(BuildContext context) { return Scaffold( // StreamBuilder,须要一个stream,和一个builder body: StreamBuilder<CatalogModel>( stream: BlocProvider.of<CatalogBloc>(context).stream, builder: (context, snapshot) { // 数据能够从snapshot.data拿到 CatalogModel catalog = snapshot.data; return CustomScrollView( // 此处省略 ); })); }应用StreamBuilder只须要给它一个Stream和一个Builder办法即可。在获取每个传入给StreamBuilder的Stream的时候还有更加简化的办法。 ...

August 2, 2020 · 5 min · jiezi

关于flutter:flutter项目搭建-windows-新建项目

1) 输出命令行, 会主动生成一个app 我的项目 flutter create myappcd myappflutter run2) flutter run 时可能会报的谬误: no connected devices因为没有手机模拟器。在andriod studio能够增加模拟器tool -> AVD manager -> create virtual Device -> 抉择须要的手机型号,这样就能够下载相应的模拟器了始终卡在“Download https://services.gradle.org/d...”网络问题,应该是gradle服务器被墙,本人下载一个放到对应的文件夹中,参考: https://jeshs.github.io/2019/... 装置好手机模拟器后能够在电脑上看到如下: 这个时候执行flutter run 就能够在手机模拟器上看到你的app界面了。

July 30, 2020 · 1 min · jiezi

关于flutter:flutter项目搭建-windows-flutter环境配置

1) 下载flutter安装包https://flutter.io/sdk-archiv...or git clone -b beta https://github.com/flutter/flutter.git 2) 配置国内镜像FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn PUB_HOSTED_URL: https://pub.flutter-io.cn 3) 配置零碎变量在零碎环境变量的Path变量中增加Flutter的bin目录门路 4) 查看flutter运行环境命令行运行 flutter doctor提醒未装置安卓SDK以及vscode插件之类的 5)装置andriod studio装置flutter dart插件 在官网下载andriod studio https://developer.android.com... 点击装置报错Unable to access Android SDK add-on list解决间接cancel掉在前面会装置,装置之前能够设置国内ip host 下载sdk https://www.cnblogs.com/sinceret/p/11123313.html6) 装置胜利,欢送页面右下角可更改sdk装置地位以及版本 7)andriod studio装置flutter dart插件 File  - Settins - Plugins  - 查找到Flutter - install,在装置Flutter插件时会主动提醒下载Dart插件,批准即可 8) 配置Flutter及Dart门路在Android Studio中关上设置,在Languages & Frameworks中能够看到多了Flutter和Dart两个选项,依照下图配置本人的            Flutter和Dart门路即可:E:flutter -》 flutter装置地址中dart sdk门路 E:flutterbincachedart-sdk -》 flutter装置地址中dart sdk门路 ...

July 29, 2020 · 1 min · jiezi

关于flutter:flutter商城项目实战一

p21创立我的项目:我的项目目录下:flutter create 我的项目名(本人起 不反对大小写 能够用下划线 比方:flutter_shop)呈现All done就是创立胜利了 2装置:Awesome Flutter Snippets点开能够看到疾速生成办法的指令stlss:StatelessWidget 动态组件 3.创立一个pages文件夹flutter举荐以下划线的模式命名点vscode右下角的no devices能够关上虚拟机ctrl+波浪线能够关上终端 4.目录构造: 5.代码:main.dart: import 'package:flutter/material.dart';import './pages/Index_page.dart';void main()=>runApp(Myapp());class Myapp extends StatelessWidget { @override Widget build(BuildContext context) { // 每个组件外边写个container当前更好扩大 例如调节边距 // debugShowCheckedModeBanner: false,右上角的debug不展现 return Container( child: MaterialApp( title:'百姓生活+', debugShowCheckedModeBanner: false, theme: ThemeData( primaryColor:Colors.pink ), home: IndexPage(), ), ); }}index_page.dart: import 'package:flutter/material.dart';class IndexPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar:AppBar(title:Text('百姓生活+')), body: Center( child:Text('百姓生活+') ), ); }}P3+P4底栏实现1根底解说谷歌推出适配平板电脑 台式机 手机 有质感 有立体感 卡片格调 有交互成果import 'package:flutter/material.dart';ios格调import 'package:flutter/cupertino.dart'; ...

July 29, 2020 · 1 min · jiezi

关于flutter:移动端跨平台技术之下的变与不变

一.跨平台,是想跨哪些平台?目前(2020/7/18)来看,挪动端跨平台需要次要集中在: 跨 PC 端与挪动端:PC 向无线过渡的晚期,心愿 PC Web 与挪动 Web 复用同一套代码跨 Native 与 Web:商品详情页等要求有一套性能差不多的 Web 页可能在端外拜访,须要跨 Native App 与 Web跨 Native 双端:出于开发效率等起因,心愿 Android、iOS 双端复用一套业务代码跨 App:一些产品性能冀望能在多个渠道投放上线,以工具类需要为主,如打车、买票、点餐在可预感的将来,可能还会有这些跨平台需要: 跨轻利用:零碎级即用即走的轻量级利用,如Android 快利用、iOS App Clips跨 IoT 设施:各种有显示屏的设施都会成为新的“端”,如车载设施、智能家居跨所有客户端:可能是伪需要,同一产品在不同平台的侧重点不同,或者并不需要把所有性能残缺地搬到各式各样的客户端设施/平台渠道上,例如快利用与 Native App 的定位显然不一样在这样的时代背景下,无论从资源老本、开发效率,还是从产品迭代、技术演进的角度来看,跨平台开发都是强需要,所以才有了层出不穷的各种跨平台计划摸索 二.层出不穷的跨平台技术细数近几年业界支流的挪动端跨平台计划,可大抵分为 3 类: Web 生而跨平台:只有有浏览器或 WebView,依靠 Web 技术即可轻松跨平台,如 Web App、PWA(Progressive Web Apps)、Hybrid App、PHA(Progress Hybrid App)容器化 Native 跨端:将 Native App 革新成标准化的容器,进而容许一套代码跨多端规范容器运行,如 React Native/Weex、Flutter小程序一码多投跨 App:国内市场中,越来越多的超级 App 反对了小程序,但各自的小程序框架并没有统一标准,于是有了Taro、kbone、uni-app等一系列跨小程序框架的计划来满足跨 App 投放产品性能的需要跨平台:Web 与生俱来 跨平台是 Web 与生俱来的劣势,浏览器和 WebView 都是 W3C 标准下的标准化 Web 容器,因而 Web 页面可能轻松投放到端外浏览器、端内 WebView、以及其它 App 提供的 WebView 中 ...

July 29, 2020 · 2 min · jiezi

关于flutter:Flutter-Notes-|quicktype-解析-json-就是这么-easy~

删除按下的那一刻,已经的所有,终将消失,云消雾散,了无痕迹。前言起初,刚入坑 Flutter,拿到后盾返回 json 串,整个人是比拟懵逼的。 回想起 Android,从开始的 JsonArray、JsonObject,直到最初的 Gson,应用起来几乎爽的嗨起~ 而面对 Flutter 的解析 json,真的让我头大,倒不是有多难,而是没找对形式办法。 说一下本文重点: 其实就是拿到接口返回 json 串,复制 quicktype 中,获取生成的 bean 即可。文末已附上链接,不想看水文的小伙伴可间接拉到底,上手 0 根底。 目标: 集体记录,微薄之力帮忙有须要的小伙伴~本文 json 对标网上找的一篇不错的 Flutter Json 解决的文章,文末已附上链接。 仅仅是个辅助工具,不蕴含对应的异样解决,毕竟,没学会走,就想跑?啥事儿不得慢慢来吗。 神器退场尽管 Flutter 提供了 dart:convert 库,让咱们无缝解析 json,然而实际上对于我一样的小白,尤其刚刚入坑的小白,上手水平还是有点费劲。 那么,有没有一个神器,能够让相似我一样 0 根底的开发者,轻而易举解析 json 呢? 闪亮退场: quicktype官网点击右上角,抉择 open quicktype: 按需抉择对应操作: 测试环节因为要害解析实体还是通过 quicktype 生成,这里简略的举个例子,让咱们一起来看,解析 json,到底如许 easy~ 一、简略的 json 串要解析的 json 串如下: { "id":"201314", "name":"HLQ_Struggle", "score" : 100}对应拷贝 quicktype 获取对应实体类: ...

July 27, 2020 · 2 min · jiezi

关于flutter:Flutter初探

背景Flutter是什么跨端开发历程:Hybrid(Webview + js) => OEM Widgets(RN、Weex) => 自渲染(Flutter)Flutter 是 Google 开源的 UI 工具包,帮忙开发者通过一套代码库高效构建多平台精美利用野心:Mobile、Web(已反对 beta 频道)、Desktop、Embedded 概览Flutter 框架总览 2D渲染引擎 Skia,原则上比 React Native 和 Weex 性能更好RN框架原理图 Flutter框架原理图 Dart && WidgetsMaterial && Cupertino其余自己之前次要从事Web端开发,对客户端开发的流程还不太理解 操作系统:Windows 10IDE:Android Studio 3.5编辑器:VS CodeAndroid SDK 版本:30.0.1Flutter 版本:1.21.0-2.0.pre.114Dart 版本:2.9.0预留硬盘空间 10Gb 以上必要时可能须要迷信上网,查看 官网文档 也倡议开启迷信上网,否则有些字体文件加载不了,左侧菜单栏会显示异样 装置踩坑为 Flutter 设定镜像配置装置 Flutter SDK,我是通过 命令行形式 装置的配置 Flutter 环境变量,不同操作系统配置形式有所不同。配置实现后在终端命令行里运行 flutter --version 查看是否配置胜利装置 Android Studio,因为后续须要 IDE 帮助装置一些 SDK、SDK Tools 和 Plugins通过 Android Studio IDE 装置 Android SDK 和一些 SDK Tools,还有 Flutter 和 Dart 插件,该过程耗时比拟长,次要是因为要下载一些很大的包(如果还要配置 AVD 虚构设施的话还要更多工夫) ...

July 23, 2020 · 1 min · jiezi

关于flutter:在flutter中增加黑夜模式以及换肤功能

应用flutter写的电影播放软件:https://github.com/Mockingbird1234/skapp 开源不易,感兴趣的小伙伴给个star吧。 在flutter减少黑夜模式和换肤其实很简略,这里须要联合mobx一起应用,对于在flutter中应用mobx,能够参考我的这篇文章,https://www.jianshu.com/p/3bf5687c58c0。 实现原理就是在全局中存储以后皮肤模式,应用MaterialApp的theme属性实现换肤。 在store中定义模式首先在store中定义全局变量,局部代码如下: var colorList = [ Colors.red, Colors.pink, Colors.purple, Colors.lightBlue, Colors.cyan, Colors.teal, Colors.green, Colors.lime, Colors.amber, Colors.orange, Colors.deepOrange, Colors.blueGrey, ];Future getThemeIndex() async { SharedPreferences prefs = await SharedPreferences.getInstance(); int themeIndex = prefs.getInt('themeIndex') ?? 0; return themeIndex; }@observable Color theme; //在主题色@computed Brightness get themeMode { return isDark ? Brightness.dark : Brightness.light; }@observablebool isDark;这里colorList用于寄存色彩,themeIndex应用SharedPreferences寄存色彩索引,独自定义isDark变量用于判断以后是否是暗黑模式。 应用Provider注入Global接下来在main.dart中注入全局变量,局部代码如下: runApp(RestartWidget( child: MultiProvider( providers: [ Provider<Global>( create: (_) => Global(prefs), ), ], child: MyApp(), ), ));@override Widget build(BuildContext context) { final Global _global = Provider.of<Global>(context); _global.getAppConfig(); _global.getAppAds(); Upgrader().clearSavedSettings(); // Upgrader().isUpdateAvailable(); final cfg = AppcastConfiguration(url: updataAppUrl, supportedOS: ['android']); _upgradeApp(_global); return Observer( builder: (_) => MaterialApp( theme: ThemeData( brightness: _global.themeMode, primarySwatch: _global.theme, platform: TargetPlatform.iOS, ), home: Scaffold( resizeToAvoidBottomPadding: false, backgroundColor: Theme.of(context).cardColor, body: _global.updataApp ? UpgradeAlert( appcastConfig: cfg, title: '发现新版本', prompt: '', showLater: false, showIgnore: false, buttonTitleUpdate: '立刻更新', debugAlwaysUpgrade: true, child: Center( child: Container( width: 0, height: 0, ), ) // debugLogging: true, ) : SplashWidget(), ), onGenerateRoute: Application.router.generator, navigatorObservers: [AppAnalysis()], ), ); }应用final Global _global = Provider.of<Global>(context);便能够获取在store中定义的变量以及变量的值。 ...

July 22, 2020 · 1 min · jiezi

关于flutter:Flutter开发之Flare动画

Flare动画简介Flutter的动画大体能够分为应用AnimationController 和Animation管制的根底动画、应用 Hero的转场动画和应用CustomPainter 的自定义动画三大类。除此之外,Flutter还反对矢量动画,是一种相似Android开发中的Lottie动画。 Flare是一家能够疾速制作矢量动画的网站,提供专门的Flutter组件来承载网站导出的动画文件,应用Flare创立的动画不仅能够无效缩小安装包的体积,还能创立更加简单壮丽的动画体验。Flare动画最早呈现在2019年12月举办的Flutter技术大会上,一经公布立马受到开发者的青睐和追捧。 作为一个业余制作矢量动画的网站,Flare提供了十分丰盛的收费矢量动画。因为Flare并没有提供桌面版的开发工具,所以创立Flare动画之前须要登录Flare官网来制作Flare动画文件,如果还没有Flare账号能够先注册一个。 Flare通常以工程模式来创立和治理动画我的项目,目前Flare反对创立动画我的项目有两类,别离是Flare和Nima,它们的区别如下。 Flare:为App和Web构建实时、疾速的动画,同时也反对构建游戏利用动画。Nima:为游戏引擎和利用构建2D动画。因为Nima次要用于构建2D游戏动画,所以如果是一般的利用开发只须要新建一个Flare我的项目即可。关上Flare官网,而后点击【Your Files】菜单即可新建一个Flare我的项目,如下图所示。 而后,零碎会初始化一个空白的工作区用于开发者创立和制作动画文件,如下图所示。在工作区的左上角有两个切换按钮,别离是SETUP和ANIMATE,示意两种不同的工作模式。其中,SETUP模式用于导入和绘制矢量元素,而ANIMATE模式则用于解决矢量元素的动画交互,动画交互须要用到的动画节点名称位于工作区的左下角。 通常,制作Flare动画文件是一项业余且简单的工作,如果只是为了体验Flare动画的魅力,那么能够应用Flare提供的收费矢量动画,如下图所示。 制作Flare动画如果咱们须要创立Flare动画,那么首先须要初始化一个动画我的项目,如下图所示。如上图所示,在工作区的左上角有两个切换按钮,别离是SETUP和ANIMATE,示意两种不同的工作模式。 SETUP:用于导入和绘制矢量元素ANIMATE用于解决矢量元素的动画交互在SETUP模式下,咱们能够通过Hierarchy树状图来查看所有控件的层级构造关系,个别顶级结点是一个artboard,能够定义scene的尺寸、背景色彩等属性。一个Flare动画能够有多个artboard,并且控件都能够领有本人的子控件,子控件会继承父控件的所有变换。如果要增加矢量元素,能够点击 SETUP模式下工作区的“+”号按钮,如下图所示。咱们以制作一个按钮为例。首先,咱们抉择菜单中的矩形,而后选中矩形,右侧会呈现属性菜单栏,能够批改地位、大小、色彩、线条等等属性,如下图所示。当然,咱们也能够按住鼠标右键(或者按住空格拖动鼠标)能够拖动画布,滚轮放大/放大,上下左右键准确调整地位,Shift+上下左右键能够大幅调整地位。接下来,咱们切换到ANIMATE模式增加动画,底下会多出一行动画控制面板,如下图。首先,关上动画时长区间,将指针拨到00:01:00(mac能够应用快捷键command+shift+左右,windows能够应用快捷键ctrl+shift+左右,一次调整10帧),并在在00:01:00处更改矩形的属性,如下图所示。而后,点击左下角的播放键,成果如下图。最初,将制作好的Flare动画文件导出即可。对于如何创立Flare动画,能够参考官网开源的例子,以及 Flare动画和Flutter动画之Flare的制作与应用。 Flare动画应用制作Flare动画文件是一项业余且简单的工作,如果只是为了体验Flare动画的魅力,那么能够应用Flare提供的收费矢量动画。首先,关上一个收费的矢量动画,而后点击面板中【OPEN IN RIVE】按钮关上Flare动画文件,如下图所示。而后,点击工作区右上角的导出图标即可导出Flare动画文件,该文件是一个flr 格局的文件,Flare动画组件操作的就是该文件。 在Flutter中开发Flare动画须要应用到flare_flutter或者smart_flare库。其中,smart_flare库是对flare_flutter库的高度封装,开发者只须要应用大量代码即可实现与Flare动画的交互。关上Flutter工程,并在pubspec.yaml文件中增加如下依赖配置。 dependencies: flare_flutter: ^2.0.5 smart_flare: ^0.2.9+1而后,应用flutter packages get命令将依赖的插件拉取到本地。而后,将之前导出的flr动画文件拷贝到assets资源目录下,并在pubspec.yaml配置文件中注册该动画文件,如下所示。 assets: - assets/button-animation.flr如果只是单纯的加载动画文件,而不须要解决与动画交互,那么能够应用flare_flutter库提供的FlareActor组件来加载动画文件,如下所示。 FlareActor( "assets/Shake.flr", animation: "idle", alignment: Alignment.center, fit: BoxFit.contain)其中,Shake.flr示意Flare动画文件的名称,animation示意动画的初始节点。通常,flr文件会有多个动画节点,能够应用artboard.getNode(String name)办法获取动画的节点,而后通过节点来对动画进行准确地管制。 flare_flutter库应用应用flare_flutter库执行动画交互操作时,须要咱们继承FlareControls类,并对initialize()、advance()和setViewTransform()三个办法进行重写,如下所示。 initialize():个别用于动画的初始化,因为FlareActor控件曾经构建实现,所以能够在此办法中获取动画节点。setViewTransform():每执行一帧动画都会调用此办法。advance():在每一次动画行将被刷新的时候调用。例如,上面是应用flare_flutter库实现登录的动画,在此登录交互动画中,成果如下图。 在下面的动画交互中,次要蕴含如下6种动画交互事件,别离是: idle:无任何操作时的状态(熊的身材会上下浮动和眨眼睛)test:当咱们在 email 输入框中输出时的状态(熊会看向输入框,且随着你输出的长度旋转头部)hands_up:当咱们在 password 输入框中输出时的状态 (熊会用手蒙上眼睛)hands_down:当咱们在 password 输入框输出实现时的状态 (熊会放下双手)fail:当咱们登录失败时的状态(熊会做出惆怅的表情)success:当咱们登录胜利时的状态(熊会做出快乐的表情)那么如果要对用户的行为进行精准的响应,那么就须要咱们继承FlareControls,而后通过ActorNode的artboard.getNode(String name)获取节点后执行对于的事件,如下所示。 class FlareSignInController extends FlareControls { ActorNode _faceControl; Mat2D _globalToFlareWorld = Mat2D(); Vec2D _caretGlobal = Vec2D(); Vec2D _caretWorld = Vec2D(); Vec2D _faceOrigin = Vec2D(); Vec2D _faceOriginLocal = Vec2D(); bool _hasFocus = false; String _password; static const double _projectGaze = 60.0; @override bool advance(FlutterActorArtboard artboard, double elapsed) { super.advance(artboard, elapsed); Vec2D targetTranslation; if (_hasFocus) { Vec2D.transformMat2(_caretWorld, _caretGlobal, _globalToFlareWorld); _caretWorld[1] += sin(new DateTime.now().millisecondsSinceEpoch / 300.0) * 70.0; Vec2D toCaret = Vec2D.subtract(Vec2D(), _caretWorld, _faceOrigin); Vec2D.normalize(toCaret, toCaret); Vec2D.scale(toCaret, toCaret, _projectGaze); Mat2D toFaceTransform = Mat2D(); if (Mat2D.invert(toFaceTransform, _faceControl.parent.worldTransform)) { Vec2D.transformMat2(toCaret, toCaret, toFaceTransform); targetTranslation = Vec2D.add(Vec2D(), toCaret, _faceOriginLocal); } } else { targetTranslation = Vec2D.clone(_faceOriginLocal); } Vec2D diff = Vec2D.subtract(Vec2D(), targetTranslation, _faceControl.translation); Vec2D frameTranslation = Vec2D.add(Vec2D(), _faceControl.translation, Vec2D.scale(diff, diff, min(1.0, elapsed * 5.0))); _faceControl.translation = frameTranslation; return true; } @override void initialize(FlutterActorArtboard artboard) { super.initialize(artboard); _faceControl = artboard.getNode("ctrl_face"); if (_faceControl != null) { _faceControl.getWorldTranslation(_faceOrigin); Vec2D.copy(_faceOriginLocal, _faceControl.translation); } play("idle"); } @override void onCompleted(String name) { play("idle"); } @override void setViewTransform(Mat2D viewTransform) { Mat2D.invert(_globalToFlareWorld, viewTransform); } void lookAt(Offset caret) { if (caret == null) { _hasFocus = false; return; } _caretGlobal[0] = caret.dx; _caretGlobal[1] = caret.dy; _hasFocus = true; } void setPassword(String value) { _password = value; } bool _isCoveringEyes = false; coverEyes(cover) { if (_isCoveringEyes == cover) { return; } _isCoveringEyes = cover; if (cover) { play("hands_up"); } else { play("hands_down"); } } void submitPassword() { if (_password == "bears") { play("success"); } else { play("fail"); } }}因为应用flare_flutter库实现登录动画比较复杂,所以具体的代码就不多解说,有趣味的能够看看源码:登录动画源码。 ...

July 21, 2020 · 3 min · jiezi

关于flutter:2020年20个Flutter最漂亮的UI库和项目

Best-Flutter-UI-Templates地址:https://github.com/mitesh77/Best-Flutter-UI-Templates The History of Everything地址:https://github.com/2d-inc/HistoryOfEverything flame一款简洁的Flutter游戏引擎。地址:https://github.com/flame-engine/flame flutter_swiper地址:https://github.com/best-flutter/flutter_swiper Flutter UI Kitflukit (Flutter UI Kit)是一个Flutter Widget库。地址:https://github.com/flutterchina/flukit flutter-ui-nice地址:https://github.com/nb312/flutter-ui-nice The Flutter Vignettes地址:https://github.com/gskinnerTeam/flutter_vignettes flutter_easyrefresh地址:https://github.com/xuelongqy/flutter_easyrefresh FL Chart地址:https://github.com/imaNNeoFighT/fl_chart Flutter Spinkit地址:https://github.com/jogboms/flutter_spinkit flutter_staggered_grid_view地址:https://github.com/letsar/flutter_staggered_grid_view flutter_slidable地址:https://github.com/letsar/flutter_slidable Animated Text Kit地址:https://github.com/aagarwal1012/Animated-Text-Kit flutter_ui_challenge_flight_search地址:https://github.com/MarcinusX/flutter_ui_challenge_flight_search Flutter Staggered Animations地址:https://github.com/mobiten/flutter_staggered_animations Flutter-Neumorphic地址:https://github.com/Idean/Flutter-Neumorphic Trace地址:https://github.com/trentpiercy/trace ...

July 20, 2020 · 1 min · jiezi

关于flutter:APP-开发从-0-到-1二框架与网络

框架之前做 APP 开发的时候,我都是负责 Android 组 leader,新我的项目起来,我会做技术预研,如《一套残缺的 Android 通用框架》,个别会应用 MVP 模式(当初应该是 MVVM 模式),网络申请框架应用 Retrofit,图片加载应用 Glide,图片缩放和裁剪别离应用 PhotoView 和 uCrop 等,必要时,我会写个 sample 放我的项目里,让共事能够参考。 这个也是个新我的项目,我也须要做下技术预研,Flutter 网络申请框架须要应用什么?图片加载又应用什么?文章详情,我打算应用 Markdown,这 Flutter 能实现吗?等等,这些都是须要事先做好调研。 这个我的项目,代码版本治理用 GitHub,首先新建一个 Flutter 我的项目,GitHub 也新建个公有我的项目(临时不公开吧),用如下命令将本地代码和近程 GitHub 关联起来。 echo "# andblog" >> README.mdgit initgit add README.mdgit commit -m "first commit"git remote add origin https://github.com/WuXiaolong/andblog.gitgit push -u origin master关联 OK,前面批改,就间接应用 Android Studio 自带的 Git 来提交代码。 接下来来看看 Flutter 网络申请框架应用什么?怎么应用? 网络数据起源说到网络申请框架,首先要解决数据从何而来,我没有后端(其实我能够开发),没有服务器,怎么搞?莫急,都说本系列文章是从零开发 APP,且能一个人做一个我的项目,我天然有方法。 数据我应用的 Bmob,它能够创立你想要的表,反对 RestAPI,这能够为做 APP 省去后端开发成本,当然像 Bmob 提供这样的服务有很多,就不一一介绍,Bmob 如何应用,也不说了,官网有很具体的文档,你能够点击文章底部「浏览原文」注册个账号玩玩。 ...

July 19, 2020 · 3 min · jiezi

关于flutter:APP-开发从-0-到-1一需求与准备

背景在《手把手教你做集体 app》我有说过,开发一个 APP 很大水平依赖服务端:服务端提供接口数据,而后 APP 展现;开发一个 APP,还须要美工帮助切图。对于以前的我,没接口,没美工,照样能够开发 APP ,堪称 So easy 来形容。 当初的我,仍旧一线做着 Android 开发,不过是做着 Android Framework 开发,开始了 996,最近半年更是疯狂,早晨十一二点上班也是常态……我曾经两年工夫没有写 APP 开发了,然而我还是对 APP 开发放弃了极大的关注,想着万一当前还会回来做 APP 开发呢,因而心田有个想法,要不要从零做个 APP,维持战斗力。 APP 开发有个特点,技术更新太快,前面新进去的 Kotlin、Flutter 我都有试水,但都没有理论我的项目操作,当初大家是不是都在用 Flutter 开发 APP 了吧?从零开发 APP 本想还用 Java 开发,这仿佛没什么挑战性,还是用 Flutter 玩下吧。 需要既然是从零开发 APP,问题来了,要做成什么样子的 APP 呢?好的,产品经理即刻上身,当初开发者社区品质愈发降落,好的技术文章愈发的少,做个 APP,每天精选一篇优良文章,款式布局跟公众号一样就好。 OK,站在项目经理角度,这种需要实现形式最好是小程序,但做小程序对我技术积攒没什么帮忙,还是用 Flutter 玩吧。 本系列文章面向人员:对 Flutter 开发 Android APP 有趣味,仍旧是没接口,没美工,一个人做一个我的项目。 筹备我首先把 Android Studio 降级到 4.0,运行《Flutter 初尝:从 Java 无缝过渡》例子,发现 Android Studio 基本连不上模拟器,也新建不了我的项目,报以下谬误: ...

July 19, 2020 · 1 min · jiezi

在flutter使用多色图标以iconfont为例

应用flutter写的电影播放软件:https://github.com/Mockingbird1234/skapp 开源不易,感兴趣的小伙伴给个star吧。 多色图标flutter中自定义了很多图标,我个别都会在这个网站找flutter中的图标:https://www.fluttericon.com/ 这种图标只反对纯色,如果你不会设计而且还须要多色图标,那么就能够应用阿里巴巴的图标库:https://www.iconfont.cn/ 在flutter中应用iconfont上面以我我的项目中应用iconfont的多色图标进行解说,次要用了githut一个开源我的项目:https://github.com/iconfont-cli/flutter-iconfont-cli,能够浏览这个开源我的项目的readme文件进行一步步搭建应用。 1.在我的项目文件pubspec.yml中退出flutter插件 flutter_svg { ... dependencies: # 版本号请以官网库的为准:https://github.com/dnfield/flutter_svg/tags flutter_svg: ^0.14.1 ...}留神:这里的flutter_svg最好应用0.17.3版本,经测试这个版本不会呈现什么问题,其余版本可能会有报错。 而后执行flutter插件安装操作 flutter packages get接着装置全局插件(基于nodeJs) npm install flutter-iconfont-cli -g2.生成配置文件 npx iconfont-init此时我的项目根目录会生成一个iconfont.json的文件,内容如下: { "symbol_url": "请参考README.md,复制官网提供的JS链接", "save_dir": "./lib/iconfont", "trim_icon_prefix": "icon", "default_icon_size": 18, "summary_component_name": "IconFont"}配置参数阐明: symbol_url:请间接复制iconfont官网提供的我的项目链接。请务必看清是.js后缀而不是.css后缀。如果你当初还没有创立iconfont的仓库,那么能够填入这个链接去测试:http://at.alicdn.com/t/font_1373348_ghk94ooopqr.js save_dir:依据iconfont图标生成的组件寄存的地位。每次生成组件之前,该文件夹都会被清空。 trim_icon_prefix:如果你的图标有通用的前缀,而你在应用的时候又不想反复去写,那么能够通过这种配置这个选项把前缀对立去掉。 default_icon_size:咱们将为每个生成的图标组件退出默认的字体大小,当然,你也能够通过传入props的形式扭转这个size值。 summary_component_name:就是汇总组件的名称,默认名称为IconFont,您也能够改成Icon或者您喜爱的名字。记住,它是一个类名,您必须恪守Dart中对于类名的语法规定,请尽量以大写字母结尾。 3.开始生成React规范组件 npx iconfont-flutter生成后查看您设置的保留目录中是否含有所有的图标 4.应用 图标尺寸 依据配置default_icon_size,每个图标都会有一个默认的尺寸,你能够随时笼罩。 class App extends StatelessWidget { @override Widget build(BuildContext context) { return IconFont(IconNames.alipay, size: 100); }}图标单色 单色图标,如果不指定色彩值,图标将渲染本来的色彩。如果你想设置为其余的色彩,那么设置一个你想要的色彩即可。 留神:如果你在props传入的color是字符串而不是数组,那么即便本来是多色调的图标,也会变成单色图标。 IconFont(IconNames.alipay, color: 'red');图标多色调 ...

July 17, 2020 · 1 min · jiezi

使用flutter编写一款视频播放软件

先上源码地址:https://github.com/Mockingbird1234/skapp 开源不易,喜爱的敌人能够给个star反对一下。 软件介绍skapp是一款视频播放软件,它既能播放电影,同时也能够切换音乐助手来播放支流站点的音乐,这个软件依赖接口服务端(服务端应用koajs编写,暂未开源),原理是应用苹果cms采集资源入库,应用服务端读取数据库数据进行整合,app端调用接口展现数据。所以这款软件能够实现无缝对接其余站长的数据资源。 软件界面上面通过一些截图来简略介绍下软件的性能。 这是软件的欢送界面,能够在服务端动静配置是否显示 这是软件的首页,之所以这样设计是因为过后只是想简略的做一款分类播放软件,流程不用太简单,所以底部是苹果cms的一级分类,头部是苹果cms的二级分类,底部的图应用的是iconfont里的图标,对于如何在flutter中应用这种多色图标,打算当前出个教程具体介绍下。 这是软件的预览界面,它的底色会依据电影图片的主色调进行扭转,原理是应用一个叫做colorpick的包进行拾色动静渲染,次要是模拟豆瓣电影做的这种成果。这个页面实现起来还是比较复杂的,有很多动画成果,感兴趣的能够下载软件的release版本体验下。 这是软件的播放界面,应用tencent_player进行视频播放,目前反对.m3u8、.mp4以及网页模式的播放源,能够在这个界面抉择视频播放源以及清晰度。这里当前想退出投屏的性能,然而目前还没有思路,晓得如何加投屏的小伙伴能够在评论区给我留言。 这是软件的次要功能区,因为软件性能不多,所以没有独自整个界面来进行软件设置,而是间接把性能都放到了slider外面。在这外面能够更换皮肤,更换皮肤原理是定义一个全局变量存储起来色彩,点击小圆点来批改全局变量就能够了,暗黑模式和换肤原理一样,flutter天生反对这种性能,还是十分不便的。点击音乐助手就能够切换到音乐播放界面,稍后会做介绍。直播按钮会应用支流直播源进行播放,目前可能不能应用,自定义片源性能的初衷是因为自己服务器配置较低,资源较少,应用这个性能能够在用户本地或线上搭建本人的服务端进行无缝对接,这样能够加重我本人服务器的压力。 这是点击音乐助手后切换的界面,和电影是一样的界面,实现原理是整合了另一款开源我的项目-洛雪音乐助手,服务端对立进行整合凋谢api。 这是音乐播放界面,能够切换到歌词界面(截图未提供),这里提供退出歌单,高低歌曲切换,下载音乐等性能。以上介绍了软件的大体性能,此外还有以下小性能: 搜寻广告位,别离在软件启动、电影播放以及电影暂停处减少了广告位,能够在服务端进行动静配置3.友盟统计,能够应用友盟统计性能 以上性能可能站长比拟须要。 如果你是普通用户,能够到github下载我的项目的release版本进行体验,对软件的应用形式有哪些不习惯的欢送提issue; 如果你对flutter比拟感兴趣,能够下载本我的项目源码进行钻研,集体认为对学习flutter还是比拟有帮忙的,次要应用mobx对状态进行治理,应用fluro进行路由治理 如果你是苹果cms的使用者,也能够应用此我的项目对接本人的资源,打造一款属于你本人的APP 如果大家对这种软件感兴趣,当前打算出几个教程介绍下软件装置形式以及如何进行flutter开发,flutter的上手难度集体感觉要比RN以及原生简略点。 最初还是那句话,开源不易,欢送大家到github给个star反对一下。

July 17, 2020 · 1 min · jiezi

推荐7个Flutter重磅开源项目

当初跨平台开发技术的倒退堪称热火朝天,而跨平台中的双雄则是ReactNative和Flutter。而由Google推出的Flutter目前的倒退更堪称是如日中天,大有一统各端开发的架势,以此给大家整顿了一个优质的Flutter开源我的项目,帮忙大家学习Flutter开发。@[toc] 1.Flutter仿携程App(1)利用截图: (2)实现性能及个性实现首页、搜寻、旅拍、我的四大模块;实现网络图片本地缓存;旅拍模块实现瀑布流布局;接口数据抓取携程H5端;集成友盟数据统计; (3)我的项目构造:依赖: azlistview: ^0.1.2cupertino_icons: ^0.1.2cached_network_image: ^1.1.1dio: ^3.0.3flutter_swiper: ^1.1.6flutter_staggered_grid_view: ^0.3.0flutter_splash_screen: ^0.1.0fluttertoast: ^3.1.3flutter_webview_plugin: ^0.3.8lpinyin: ^1.0.7package_info: ^0.4.0+6(4)我的项目地址:Github地址:https://github.com/wkl007/flu... 2.Flutter仿微博客户端(1)利用截图: (2)实现性能:仿微博最新版本,还原微博80%的界面,总共波及到了几十个界面和接口,用到了flutter中的大部分组件分为首页 视频 发现 音讯 我的五个模块 (3)依赖:cupertino_icons: ^0.1.2 #https://github.com/luanpotter/audioplayersaudioplayers: ^0.14.0 #https://github: com/best-flutter/flutter_swiperflutter_swiper: ^1.1.6 #https://github.com/best-flutter/flutter_page_indicatorflutter_page_indicator: ^0.0.3 #https://github.com/flutter/plugins/tree/master/packages/video_playervideo_player: # https://github:com/brianegan/chewie:chewie: ^0.9.5 #https://github.com/flutterchina/azlistviewazlistview: ^0.1.2 #https://github.com/flutterchina/lpinyinlpinyin: ^1.0.9 # https://github:com/fluttercandies/extended_text_field:extended_text_field: ^0.5.0url_launcher: 5.3.0 # https://github: com/fluttercandies/extended_nested_scroll_view:extended_nested_scroll_view: ^0.4.0(4)我的项目地址:Github地址:https://github.com/huangruiLe... 3.Flutter仿抖音App(1)利用截图: (2)实现性能:高低刷视频,视频会主动加载封面 左右滑动去搜寻与集体核心 双击冒爱心点赞 看评论 切换底部Tabbar (3)我的项目构造:依赖: # 加载动画库(如同改版之后就没用到了)flutter_spinkit: ^4.1.2 # Bilibili开源的视频播放组件fijkplayer: ^0.8.3 # 根底的通明动画点击成果tapped: any # map平安取值safemap: any次要文件: ...

July 15, 2020 · 1 min · jiezi

Flutter-Notes|-记录开发过程中常用命令

准星瞄准鸡老大,biu~ 前言命令很多,只记录本人罕用的,后续应用到会及时更新~ 局部借助翻译软件,莫抬杠,有问题欢送斧正~ 已经看鸡老大玩命令行,心田各种卧槽,666. 而今 Flutter 从新开始,也要尝试把握一波命令行的玩法,万一哪儿天能够向鸡老大秀一波呢~ 期待鸡老大对我 666~ 常用命令汇总对于不相熟,或者遗记了有哪儿些好用的命令,能够间接查问帮忙手册: flutter -h同等于: flutter --help针对想查看某个命令运行时具体日志,可在前面间接 -v 或者 --verbose,例如: flutter help -v同等于: flutter help --verbose当然 Android Studio Tools 工具也为咱们列出几个比拟罕用的命令: 同样还有一个大杀器: killall -9 dart有时候会发现卡住不动,可能网络起因,可能其它起因,这个时候就能够应用这个命令,间接完结掉 dart,开启上面的工作咯。 一、Flutter 基本操作1.1 检测 Flutter 开发环境flutter doctor1.2 更新版本flutter upgrade1.3 强制更新版本flutter upgrade --force1.4 治理 Flutter 软件包flutter pub cache:应用零碎 pub 缓存包。deps:打印依赖包的依赖关系。downgrade:应用 Flutter 降级包。get:获取 Flutter 软件包。global:应用 pub 全局包。outdated:剖析并提醒以后可降级的依赖包。pub:将其余参数传递给Dart的 pub 工具。publish:将以后包公布到 pub.dev。run:运行包到可执行文件。test:运行测试软件包。upgrade:在 Flutter 降级软件包。uploader:治理 pub.dev 上的软件包的上传者。version:获取 pub 版本。1.5 列出 Flutter 版本flutter version1.6 列出以后已连贯的设施列表flutter devices1.7 运行软件到设施flutter run1.8 列出 Flutter 渠道flutter channel1.9 删除 build 和 .dart_tool 目录flutter clean2.0 显示运行 Flutter 利用的日志输入flutter logs二、Flutter 我的项目相干2.1 创立我的项目flutter create [项目名称]2.2 创立我的项目并输入日志flutter create [项目名称] -v2.3 运行 Flutter 测试flutter test2.4 构建 Flutterflutter assemble2.5 测量利用启动工夫flutter run --trace-startup --profile2.6 获取以后已连贯设施截图flutter screenshot三、Flutter 打包相干3.1 构建对应包flutter build ...

July 14, 2020 · 1 min · jiezi

Flutter-Notes-|-我用到的一些插件整理

追寻鸡老大,点击积攒~前言一个我的项目的开始和完结,总会遇到很多意料之外的货色。 大神和菜鸟的区别,个人感觉更多的是大神破费了很多私下工夫去理解每个问题的基本是什么,而我这小菜鸟,仅仅网上浪一圈,Fix 了,OK 了,Commit 没事了。 鸡老大说过,不要停留问题外表,深究其根本原因。 时隔几年,我仍旧停留外表,徘徊之余望着鸡老大的背影,瞎想。 好了,闲篇儿不扯了,点滴积攒吧。 回顾前几周刚入坑 Flutter,真的是贼好受,最近慢慢处于稳固环境了,正好总结下期间应用的感觉不错的插件。 插件大汇总好的工具,总会让人事倍功半,一起来看~ 每个人认知不一样,有可能我感觉不错的,你感觉不咋滴,所以这里针对封装就不举荐了,自行搜寻~ 这里举荐多去官网提供的插件库中逛逛,总有不一样的发现: https://pub.flutter-io.cn/flu...1、dio:网络申请神器插件地址: https://pub.flutter-io.cn/pac...GitHub 地址: https://github.com/flutterchi...2、fluro:路由治理(简略可了解为 Android 的跳转页面)插件地址: https://pub.flutter-io.cn/pac...GitHub 地址: https://github.com/theyakka/f...3、shared_preferences:本地长久化存储(存储简略信息)插件地址: https://pub.dev/packages/shar...GitHub 地址: https://github.com/flutter/pl...4、Permission_handler:权限治理在 Android 最后实现动静权限治理时,真的头疼,不过当初 Flutter 也有成熟的动静权限治理,贼不便。 插件地址: https://pub.flutter-io.cn/pac...GitHub 地址: https://github.com/Baseflow/f...5、device_info:获取设施信息插件地址: https://pub.flutter-io.cn/pac...GitHub 地址: https://github.com/flutter/pl...6、package_info:版本相干信息获取插件地址: https://pub.dev/packages/pack...GitHub 地址: https://github.com/flutter/pl...7、url_launcher:跳转第三方 App插件地址: https://pub.dev/packages/url_...GitHub 地址: https://github.com/flutter/pl...8、event_bus:事件总线怎么说呢,你能够通过订阅指定的某个事件,在特定的场合执行某个事件。 插件地址: https://pub.dev/packages/even...GitHub 地址: https://github.com/marcojakob...9、crypto:加解密插件地址: https://pub.flutter-io.cn/pac...GitHub 地址: https://github.com/dart-lang/...10、Fluwx:微信领取、分享这个插件提供独自分享版本,按需应用即可。 GitHub 都有详细描述,认真查看,上手难度为 0。 插件地址: https://s0pub0dev.icopy.site/...GitHub 地址: https://github.com/OpenFlutte...11、share:原生分享插件地址: https://pub.flutter-io.cn/pac...GitHub 地址: https://github.com/flutter/pl...12、flutter_easyloading:加载框插件地址: https://pub.flutter-io.cn/pac...GitHub 地址: https://github.com/huangjiank...13、flutter_html:加载 Html插件地址: https://pub.dev/packages/flut...GitHub 地址: ...

July 14, 2020 · 1 min · jiezi

Flutter-Android初始化流程

FlutterView继承SurfaceView,它的外部有两个线程即主线程和渲染线程,应用渲染线程中向屏幕上绘图能够防止主线程阻塞,从而进步了程序的反应速度。应用了双缓冲机制。实现BinaryMesaenger接口, 这个接口定义了Android代码和Flutter代码间接通信的形式,此接口还有2个外部接口。 FlutterView实现了这个接口,领有了和flutter通信的的能力实现TextureRegistry接口,这个接口次要是创立一个SurfaceTexture对象,应用SurfaceTextureEntry包装起来,领有惟一的ID。实现onAccessibilityChanged接口,次要用来监听系统accessibility 状态变动的。创立一大堆Channel用于Android和flutter通信 navigationChannel = new NavigationChannel(dartExecutor); keyEventChannel = new KeyEventChannel(dartExecutor); lifecycleChannel = new LifecycleChannel(dartExecutor); localizationChannel = new LocalizationChannel(dartExecutor); platformChannel = new PlatformChannel(dartExecutor); systemChannel = new SystemChannel(dartExecutor); settingsChannel = new SettingsChannel(dartExecutor);创立FlutterNativeView //初始化 mNativeView = new FlutterNativeView(activity.getApplicationContext()); OnAccessibilityChangeListener AccessibilityStateChangeListener 创立一堆成员变量 mIsSoftwareRenderingEnabled 硬件加速渲染相干的 dartExecutor = mNativeView.getDartExecutor(); flutterRenderer = new FlutterRenderer(mNativeView.getFlutterJNI()); mIsSoftwareRenderingEnabled = mNativeView.getFlutterJNI().nativeGetIsSoftwareRenderingEnabled(); mMetrics = new ViewportMetrics(); mMetrics.devicePixelRatio = context.getResources().getDisplayMetrics().density; setFocusable(true); setFocusableInTouchMode(true); //attach到以后Activity mNativeView.attachViewAndActivity(this, activity); mSurfaceCallback = new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { assertAttached(); mNativeView.getFlutterJNI().onSurfaceCreated(holder.getSurface()); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { assertAttached(); mNativeView.getFlutterJNI().onSurfaceChanged(width, height); } @Override public void surfaceDestroyed(SurfaceHolder holder) { assertAttached(); mNativeView.getFlutterJNI().onSurfaceDestroyed(); } };FlutterNativeView创立if (nativeView == null) { mNativeView = new FlutterNativeView(activity.getApplicationContext()); } else { mNativeView = nativeView; } public FlutterNativeView(@NonNull Context context, boolean isBackgroundView) { mContext = context; mPluginRegistry = new FlutterPluginRegistry(this, context); mFlutterJNI = new FlutterJNI(); mFlutterJNI.addIsDisplayingFlutterUiListener(flutterUiDisplayListener); this.dartExecutor = new DartExecutor(mFlutterJNI, context.getAssets()); mFlutterJNI.addEngineLifecycleListener(new EngineLifecycleListenerImpl()); attach(this, isBackgroundView); assertAttached(); }FlutterPluginRegistry是actitiy和flutterView绑定关系操作类,而FlutterJNI创立时,将绑定绘制、跨平台通信、生命周期的监听办法。mFlutterJNI ,Engine层c++办法的一个封装类。所有Flutter JNI的调用都汇合在这个类中。 一个FlutterJNI对象是和一个Platform View相关联,所以蕴含一个nativePlatformViewId来标识 attach(this, isBackgroundView); private void attach(FlutterNativeView view, boolean isBackgroundView) { mFlutterJNI.attachToNative(isBackgroundView); dartExecutor.onAttachedToJNI(); } public void attachToNative(boolean isBackgroundView) { ensureRunningOnMainThread(); ensureNotAttachedToNative(); nativePlatformViewId = nativeAttach(this, isBackgroundView); }总结 ...

July 14, 2020 · 4 min · jiezi

flutter-GridView-九宫格

我收集了一些学习用的材料,其中蕴含了很多学习,面试,中高进阶fluuter材料,还有很多视频详解,如果有同学想进一步理解,详情请看文末。也欢送各路大神门前来装X。 1 引言 GridView是罕用可滚动组件之一,在Flutter中通常应用GridView构建二维网格列表,GridView创立办法有五种,形容如下 GridView的构造函数办法,一次性构建所有的子条目,实用于大量数据 GridView.builder形式来构建,懒加载模式,实用于大量数据的状况 GridView.count形式来构建,实用于固定列的状况,实用于大量数 GridView.extent形式来构建,实用于条目有最大宽度的限度的状况,实用于大量数据的状况下 GridView.custom 形式来构建,可配置子条目标排列规定也可配置子条目标渲染加载模式 2 滑动组件的私有属性 GridView也是滑动组件系列中的一个,它也有滑动组件一些专用的属性,简略形容如下: ///滑动方向 Axis scrollDirection = Axis.vertical, ///是否滑动到底部 bool reverse = false, ///滑动控制器 ScrollController controller, ///是否应用默认的控制器 bool primary, ///滑动到边界时的回弹成果 ScrollPhysics physics, ///内边距 EdgeInsetsGeometry padding, 3 通过GridView的构造函数来创立 通过GridView的构造函数来构建,通过参数children来构建GridView中应用到的所有的子条目,通过参数gridDelegate配置SliverGridDelegate来配置子条目标排列规定。 SliverGridDelegate申明为abstract形象的,所以须要应用它的子类来构建。 SliverGridDelegate有两个间接的子类SliverGridDelegateWithFixedCrossAxisCount和SliverGridDelegateWithMaxCrossAxisExtent。 通过SliverGridDelegateWithFixedCrossAxisCount来构建一个横轴为固定数量的子条目标GridView,如下图所示。 对应代码如下: ///GridView的根本应用class GridViewBaseUsePage extends StatefulWidget { @override State createState() { return ScrollHomePageState(); }} class ScrollHomePageState extends State { @override Widget build(BuildContext context) { return Scaffold( appBar: new AppBar( title: Text("GridView根本应用"), ), ///构建九宫格数据数据 body: buildGridView1(),// body: buildGridView2(), ); } ///GridView 的根本应用 ///通过构造函数来创立 Widget buildGridView1() { return GridView( ///子Item排列规定 gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( //横轴元素个数 crossAxisCount: 3, //纵轴间距 mainAxisSpacing: 10.0, //横轴间距 crossAxisSpacing: 10.0, //子组件宽高长度比例 childAspectRatio: 1.4), ///GridView中应用的子Widegt children: buildListViewItemList(), ); } ///GridView 的根本应用 ///通过custom形式来创立 Widget buildGridView() { return GridView.custom( cacheExtent: 200, ///子Item排列规定 gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( ///子Item的最大宽度 maxCrossAxisExtent: 100, //纵轴间距 mainAxisSpacing: 10.0, //横轴间距 crossAxisSpacing: 10.0, //子组件宽高长度比例 childAspectRatio: 1.4, ), ///子条目标构建模式 childrenDelegate: ///懒加载的模式 SliverChildBuilderDelegate((BuildContext context, int index) { return buildListViewItemWidget(index); })); } List buildListViewItemList(){ List list = []; ///模仿的8条数据 for (int i = 0; i ///创立GridView应用的子布局 Widget buildListViewItemWidget(int index) { return new Container( ///内容剧中 alignment: Alignment.center, ///依据角标来动静计算生成不同的背景色彩 color: Colors.cyan[100 * (index % 9)], child: new Text('grid item $index'), ); }} 属性配置阐明如下图所示: 通过SliverGridDelegateWithMaxCrossAxisExtent来构建横轴Item数量不固定的GridView,其程度方向Item个数由maxCrossAxisExtent和屏幕的宽度以及padding和mainAxisSpacing来独特决定。 如下图所示,屏幕分辨率为750*1334的4.7英寸的手机,屏幕宽度逻辑橡素为375.0,屏幕比例devicePixelRatio为2.0。 通过SliverGridDelegateWithMaxCrossAxisExtent配置的子条目设置maxCrossAxisExtent最大宽度为120,时,如下图所示,GridView每一行显示3列。 当本配置maxCrossAxisExtent最大宽度为80,如下图所示,GridView第一行显示4列。 当然当指定一个maxCrossAxisExten值后,在不同手机屏幕分辨率上,每一行展现的列数也有所不同。 4 GridView.count与GridView.extent形式来创立 GridView的count用来构建每行有固定列数的宫格布局,参数crossAxisCount为必选参数,用来配置列数,与应用GridView通过SliverGridDelegateWithFixedCrossAxisCount形式来构建成果一至,根本应用代码如下: ///GridView 的根本应用///通过count形式来创立Widget buildGridView3() { return GridView.count( ///每行的列数 crossAxisCount: 4, //纵轴间距 mainAxisSpacing: 10.0, //横轴间距 crossAxisSpacing: 10.0, ///所有的子条目 children: buildListViewItemList(), );} GridView的extent用来构建列数不固定,限度每列的最大宽度或者高度的的宫格布局,参数maxCrossAxisExtent为必选参数,用来配置每列容许的最大宽度或者是高度,与应用GridView通过SliverGridDelegateWithMaxCrossAxisExtent形式来构建成果一至,根本应用代码如下: ///GridView 的根本应用///通过count形式来创立Widget buildGridView4() { return GridView.extent( ///每列Item的最大宽度 maxCrossAxisExtent: 120, //纵轴间距 mainAxisSpacing: 10.0, //横轴间距 crossAxisSpacing: 10.0, ///所有的子条目 children: buildListViewItemList(), );} 5 GridView.builder形式来创立 在下面形容到的GridView构造函数、count办法与extent形式来构建,都是一次性将所有的子Item构建进去,所以只实用于大量的数据 GridView的builder形式来构建,是通过懒加载模式来的,参数gridDelegate用来配置子Item的排列规定,与GridView的构造函数中gridDelegate应用统一,可别离应用SliverGridDelegateWithFixedCrossAxisCount构建固定列数的宫格和SliverGridDelegateWithMaxCrossAxisExtent构建不固定列数,固定条目最大宽度或者高度的宫格,根本应用代码如下: ///通过builder形式来创立Widget buildGridView5() { return GridView.builder( ///缓存区域 cacheExtent: 120, ///内边距 padding: EdgeInsets.all(8), ///条目个数 itemCount: 100, ///子Item排列规定 gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( ///子Item的最大宽度 maxCrossAxisExtent: 100, //纵轴间距 mainAxisSpacing: 10.0, //横轴间距 crossAxisSpacing: 10.0, //子组件宽高长度比例 childAspectRatio: 1.4, ), ///懒加载构建子条目 itemBuilder: (BuildContext context,int index){ return buildListViewItemWidget(index); }, );} https://shimo.im/docs/dYkqrQcyr98jPKYX/ 《android学习面试fulutter进阶材料收费获取》,可复制链接后用石墨文档 App 或小程序关上。

July 14, 2020 · 1 min · jiezi

Flutter-Notes-|-Android-借壳分享微信

每个生命体的存在,其实实质都是一个简单的过程。很多时候,无需谋求完满的现实状况,毕竟,You are just you。 免责申明为了防止免费的小哥哥干我,或者呈现其它不好的状况,这里特意注明下: 本文如同题目一样,只属于集体笔记,仅限技术分享~ 如呈现其余状况,一律与自己无关~ 本文如同题目一样,只属于集体笔记,仅限技术分享~ 如呈现其余状况,一律与自己无关~ 本文如同题目一样,只属于集体笔记,仅限技术分享~ 如呈现其余状况,一律与自己无关~ 前言前段时间,公司忽然来一需要: 调研某款 App Android 版微信分享起源动静原理以及实现形式第一工夫,当然是看看网上有没有前辈开源,借鉴(CV 大法)一波。 查问后果真的是悲喜交加: 开森的是,有人钻研过这个货色,也封装好了对应的 SDK。喜剧的是免费,目前已理解的状况最低 100。对于自身在帝都讨生活的落魄小 Android 而言,无疑是一笔巨款 (手动滑稽~勿喷~)。 都说穷人家的孩子早当家,不得已开始了逆向、剖析之路 ???????????? 相干代码已上传 GitHub,当然为了不给本人找事儿,本地命中库就不提供了,本人逆向去拿吧,地址如下: https://github.com/HLQ-Strugg...效果图空谈无用,来个理论效果图最棒,这里就以我幻想殿堂 App 为例进行测试咯。 筹备工具基于集体理解简略概述: ApkTools: 个别就是为了改包、回包,捎带脚拿个资源文件。ClassyShark: 一款贼不便剖析 Apk 工具,个别用于看看大厂都玩啥。dex2jar: 将 .dex 文件转换为 .class 文件。JD-GUI: 次要是查看反编译后的源代码。上面附上相干工具网盘链接: 链接:https://pan.baidu.com/s/1Ll5c... 明码:20fl实战开搞在正式开始前,先来见识下 ClassyShark 这个神器吧。 一、Hi,ClassyShark首先进入你下载好的 ClassyShark.jar 目录中,随后执行如下命令即可: java -jar ClassyShark.jar示意图如下: 随后在关上的可视化工具中将想看的 Apk 间接拖进去即可: 拖进去之后点击包名,会有一个对以后 Apk 的简略概述: 点击 Methods count 能够查看以后 Apk 办法数: ...

July 14, 2020 · 7 min · jiezi

Flutter-engine整体架构

整体框架 Flutter框架是一个分层的构造,每个层都建设在前一层之上。 最上层embedder,提供五个thread,将引擎移植到平台的中间层代码 渲染设置,原生插件,打包,线程治理,事件循环交互操作。 次要对应engine外面shell相干模块,common是对外的对立接口,gpu是gpu相干的对立接口,platform上面的对应的不同平台的撑持,分辨是哦android,darwin,embedder,fuchsia,glfw,linux,windows,common。其次是profiling,性能调优方面的反对。 engine/embedder层的架构 创立四个线程 并把以后线程设置platform thread 在GPUThread创立rasterizer在platform thread(APP主线程) 创立PlatformView 并获取其VSyncWaiter传递给Engine创立IO manager 在 IO 线程上创立engine 在UI线程上 实际上就是创立上面这四个 std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread if (!shell->Setup(std::move(platform_view), // engine_future.get(), // rasterizer_future.get(), // io_manager_future.get()) // )Platform Task Runner依据代码在初始化Engine的时候,将以后线程设置为PlatformTaskRunner的Thread,是Flutter和Native交互的桥梁,而且官网要求所有和Flutter的交互必须产生在PlatformThread中。 android app 过程所有的音讯都是通过 Platform Task Runner 来承受解决 以android为例子,platform_view_android模块就是Flutter嵌入的Java代码和Flutter 的C / C ++代码之间的接口,ui相干就跑在RasterTaskRunner中,实际上就是GPU task runner中,和原生零碎相干就跑在platformTaskRunner UI task runnerEngine执行Dart root isolate代码,将其转换为layer tree视图构造。这个线程的过载会间接导致卡顿掉帧。 GPU task runnerGPU Task Runner中的模块负责将Layer Tree提供的信息转化为理论的GPU指令。 GPU Task Runner同时也负责配置管理每一帧绘制所须要的GPU资源,这包含平台Framebuffer的创立,Surface生命周期治理,保障Texture和Buffers在绘制的时候是可用的。 GPU Runner的过载会导致Flutter利用的卡顿。 用户不能向GPU task runner提交工作。 ...

July 14, 2020 · 1 min · jiezi

Flutter应用开发之webviewflutter插件

简介在挪动利用开发中,常常会遇到加载网页的需要,关上网页通常有两种形式,即在利用内应用内置的组件关上和应用零碎自带的浏览器关上。不过,在Flutter利用开发中,因为官网并没有提供相似Webview的网页加载组件,所以如果我的项目中波及网页加载须要应用第三方插件库,如webview_flutter、flutter_webview_plugin等。 其中,webview_flutter是Flutter官网开发和保护的网页加载插件库,而flutter_webview_plugin则是Flutter开源社区推出的网页加载插件。两个插件性能都差不多,都反对加载本地html文本、Flutter调用js以及js调用Flutter等,然而我倡议应用官网推出的插件,因为它会继续的跟进已知的问题。 和其余Flutter插件的应用形式一样,应用webview_flutter之前须要先在pubspec.yaml文件中增加依赖脚本,如下所示。 dependencies: webview_flutter: ^0.3.22+1而后,咱们应用flutter packages get命令将webview_flutter插件拉取到本地后,就能够应用它进行网页加载开发了。 根本应用如下所示,是WebView组件的构造函数。 WebView({ Key key, this.onWebViewCreated, //WebView创立实现之后的回调 this.initialUrl, // 初始化 URL this.javascriptMode = JavascriptMode.disabled, //JS执行模式,默认是不调用 this.javascriptChannels, // JS能够调用Flutter 的通道 this.navigationDelegate, // 路由委托,能够应用它执行拦挡操作 this.gestureRecognizers, // 手势相干 this.onPageStarted, //开始加载页面回调 this.onPageFinished, // 页面加载实现的回调 this.onWebResourceError, //资源加载失败回调 this.debuggingEnabled = false, this.gestureNavigationEnabled = false, this.userAgent, this.initialMediaPlaybackPolicy = AutoMediaPlaybackPolicy.require_user_action_for_all_media_types, })应用时,只须要依照参数传递对应的值即可。不过,在理论应用前,为了方便使用,咱们个别会对它进行二次封装,次要是界面和性能的封装。上面是我封装的一个能够加载本地和网络文件的WebViewPage。 class WebViewPage extends StatefulWidget { String url; final String title; final bool isLocalUrl; WebViewController _webViewController; WebViewPage({this.url, this.isLocalUrl = false, this.title}); @override _WebViewPage createState() => _WebViewPage();}class _WebViewPage extends State<WebViewPage> { JavascriptChannel jsBridge(BuildContext context) => JavascriptChannel( name: 'jsbridge', // 与h5 端的统一 不然收不到音讯 onMessageReceived: (JavascriptMessage message) async{ debugPrint(message.message); }); @override Widget build(BuildContext context) { return Scaffold( appBar: _buildAppbar(), body: _buildBody() ); } _buildAppbar() { return AppBar( elevation: 0, backgroundColor: Color(0xccd0d7), title: Text(widget.title, style: TextStyle(color: Colors.black),), centerTitle: true, leading: IconButton(icon: Icon(Icons.arrow_back, color: Color(0xFF23ADE5),), onPressed: () { }) ); } _buildBody() { return Column( children: <Widget>[ SizedBox( height: 1, width: double.infinity, child: const DecoratedBox(decoration: BoxDecoration(color: Color(0xFFEEEEEE))), ), Expanded( flex: 1, child: WebView( initialUrl: widget.isLocalUrl ? Uri.dataFromString(widget.url, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')) .toString(): widget.url, javascriptMode: JavascriptMode.unrestricted, javascriptChannels: <JavascriptChannel>[ jsBridge(context) ].toSet(), onWebViewCreated: (WebViewController controller){ widget._webViewController = controller; if(widget.isLocalUrl){ _loadHtmlAssets(controller); }else{ controller.loadUrl(widget.url); } controller.canGoBack().then((value) => debugPrint(value.toString())); controller.canGoForward().then((value) => debugPrint(value.toString())); controller.currentUrl().then((value) => debugPrint(value)); }, onPageFinished: (String value){ widget._webViewController.evaluateJavascript('document.title') .then((title) => debugPrint(title)); }, ), ) ], ); }//加载本地文件 _loadHtmlAssets(WebViewController controller) async { String htmlPath = await rootBundle.loadString(widget.url); controller.loadUrl(Uri.dataFromString(htmlPath,mimeType: 'text/html', encoding: Encoding.getByName('utf-8')) .toString()); }}应用时,只须要依照传入对应的属性即可。须要阐明的是,加载本地Html文件时,须要在pubspec.yaml文件中申明这个Html文件,如下所示。 ...

July 11, 2020 · 2 min · jiezi

Flutter-自定义单选控件

在Flutter 利用开发中,常常会遇到各种单选成果,尽管官网提供了Radio组件,然而并不能满足咱们理论的开发需要,所以往往还须要自定义控件能力满足平时的开发需要。上面就平时开发中用到的单选进行介绍: 自定义SegmentBar对于分段组件大家必定不会生疏,次要是实现多个分段,实现单选性能,成果如下图。话不多说,间接上代码: class SegmentBarView extends StatefulWidget { List<String> datas; Function(String) onSelected; int defaultIndex=0; SegmentBarView({@required this.datas, this.onSelected,this.defaultIndex}); @override _SegmentBarViewState createState() => _SegmentBarViewState();}class _SegmentBarViewState extends State<SegmentBarView> { List<String> sdkLists; String selectItem; @override void initState() { super.initState(); sdkLists = widget.datas; selectItem=sdkLists[widget.defaultIndex]; } @override Widget build(BuildContext context) { return SingleChildScrollView( scrollDirection: Axis.horizontal, child: Container( padding: EdgeInsets.only(left: 10, right: 10), child: Row( children: _buildSegments(sdkLists), ), ), ); } _buildSegments(List list) { if(list == null) { return Container(); } List<Widget> items = List(); list.forEach((item){ if(item != null) { items.add(Container( padding: EdgeInsets.only(top: 8,bottom: 8), child: _buildItem(item), )); } }); return items; } _buildItem(String item) { if(selectItem == item) { return Container( height: 34, child: RaisedButton( shape: RoundedRectangleBorder(// borderRadius: BorderRadius.circular(15) ), color: Color(0xFF00A6DE), onPressed: (){ }, child: Text(item,style: TextStyle(color: Colors.white),), ), ); }else { return Container( height: 34, child: OutlineButton( borderSide: BorderSide(color: Color(0xFFcccccc),width: 0.5), onPressed: (){ updateGroupValue(item); }, child: Text(item), ), ); } } updateGroupValue(String item) { if(item == selectItem) { return; }else { selectItem = item; widget.onSelected(selectItem); setState(() { }); } } }应用的时候,只须要依照构造函数传入对应的参数即可。 ...

July 10, 2020 · 2 min · jiezi

Flutter-Notes|FlutterApk-大小优化探索

追赶,摸索,永不停歇~ 前言还记得刚入坑 Flutter 打包时,被深深震惊了一番,卧槽,这包好大! ✓ Built build/app/outputs/apk/release/app-release.apk (23.8MB). 足足将近 24 MB,第一反馈真的懵逼了。 当然间接提交市场后,也是被人各种 diss,起因还是没什么性能,包贼大,用户下载贼不难受。 强烈要求优化 Apk 大小。 既然是摸索,前提我还是个刚入 Flutter 坑的小白白,所以嘛,不免不全面,欢送各位大佬拍砖、指导~ 摸索之路 一部曲首先,我首次打包的形式如下: 雷同应用上面的命令(默认带有 --release): flutter build apk一、熊猫压缩法(缩小 0.7 MB)首先第一想法,图片我没做压缩,同样通过查看后,发现图片在 apk 占比为 4.1% : 2.3 % Flutter 援用到的资源文件;1.8% Android 启动页的背景图。最初,咱们通过国宝之手试试最初能缩小多少? 这里别离针对 Flutter 下图片资源、Android/iOS 启动页进行压缩。 再次运行 build apk 后,实现输入如下日志: ✓ Built build/app/outputs/apk/release/app-release.apk (23.1MB).再来看 Apk 中图片的占比以及升高到 1%: 最终 Apk 大小间接缩小了 0.7 MB,还是比拟爽的。 二、so 优化大法(缩小 14 MB)做 Android 的小伙伴晓得,对于咱们这些小厂没能力搞动静下发 so 的小渣渣而言,只能默默逆向大厂 Apk,看看人家是怎么做的,而后借(抄)鉴(袭)。 ...

July 10, 2020 · 5 min · jiezi

Canonical通过Flutter启用Linux桌面应用程序支持

子标题:Ubuntu团队为所有Linux发行版上的Flutter应用程序制作了一个新的基于GTK +的主机。此文翻译自:https://medium.com/flutter/an... 作者:克里斯·塞尔斯(Chris Sells)(Google)和肯·范丁(Ken VanDine)(Canonical) Google 对 Flutter 的指标始终是提供一个可移植的工具包,以构建媲美本机速度运行的精美UI,无论您应用的是哪个平台。为了验证该性能,咱们首先关注于Android和iOS挪动平台,咱们曾经在Google Play上看到了8万多个疾速,精美的Flutter应用程序。 为了获得成功,一年多来,咱们始终将重点扩大到包含桌面级体验,包含针对Web和桌面操作系统(macOS,Windows和Linux)的体验。这项工作包含对引擎进行宽泛的重构,以反对桌面款式的鼠标和键盘输入,以及可调整大小的顶级窗口。它还包含新的UI性能,能够很好地适应桌面,例如Material Density反对和NavigationRail,还能够通过Dart:FFI中的试验与根底桌面OS进行深度集成,并能够拜访零碎菜单栏和规范对话框。所有这些工作是为了确保除了适宜挪动款式的体验之外,Flutter还筹备解决功能齐全的全尺寸桌面应用程序。 为Flutter平台提供能源是咱们长期的愿景。咱们曾经在Google上看到了带有Assistant等产品的清单,所以当初咱们很快乐看到其他人利用Flutter来反对更多平台。明天,咱们很快乐与寰球最风行的台式机Linux发行版Ubuntu的发行商Canonical独特发表Flutter的Linux alpha版本。 为什么要在Linux上应用Flutter?去年,当Google发表对Flutter提供桌面级应用程序反对时,Canonical看到了一个令人振奋的机会来进行Linux发行,包含Ubuntu,这是Flutter应用程序开发人员的有吸引力的指标平台。 Flutter的原生跨平台故事正在迅速倒退,Canonical心愿成为先锋。通过在Flutter中启用桌面Linux反对,Canonical使得应用程序开发人员能够十分轻松地通过Snap Store(Linux应用程序商店)为Linux用户公布他们的应用程序。通过使Linux成为一流的Flutter平台,Canonical邀请应用程序开发人员将其应用程序公布给数百万Linux用户,并扩充可供他们应用的高质量应用程序的可用性。 无关Flutter的许多事件对于Canonical来说是令人兴奋的: 疾速倒退的应用程序开发人员生态系统多平台反对高度优化的本机应用程序古代的UI框架,反对申明式,反应式和可组合的小部件应用Visual Studio Code,Android Studio和IntelliJ的丰盛开发平台Google最后发表的Flutter桌面反对发表是从反对macOS的Alpha版本以及针对Linux和Windows的打算开始的。Canonical 通过组建一支开发人员团队与Google的开发人员单干,将Flutter的最佳体验带给大多数Linux发行版,从而对Flutter进行了重大投资。 Canonical将持续与Google单干,以进一步改善Linux反对并放弃与其余受反对平台的性能对等。 Flokk:证实Flutter已为台式机做好筹备为了证实Flutter已为台式机做好了筹备,咱们与gskinner的设计师和开发人员单干,创立了翻新的,精美的Flutter台式机应用程序。 Flokk是一个真实世界的应用程序,可解决真实世界的数据,尤其是您的Google联系人列表。 此视频地址:https://www.youtube.com/watch?time_continue=120&v=cTFJcq7UTRY&feature=emb_logo 除了可能治理您的联系人(包含搜寻联系人,增加新联系人和编辑现有联系人)之外,Flokk还使您能够将GitHub和Twitter解决与您的联系人信息。 GitHub和Twitter告诉的显示将您的联系人变成您本人的集体社交网络。而且,如果您在Flokk Contacts中没有看到您喜爱的社交网络,那么好消息是Flokk是齐全开源的,因而您能够提交PR来增加您喜爱的。 除了在社交空间中进行翻新外,Flokk还应用Flutter性能使外观看起来很棒。仅作为一个示例,深色主题不仅能够切换色彩,还能够对更改进行动画解决。 Flokk Contacts应用程序背地的创意团队由Grant Skinner领导,他以杰出的设计和施行翻新的用户体验而闻名。 Grant曾说过对于在Linux上应用Flutter: “构建Flokk Contacts应用程序非常容易!咱们简直无需进行任何调整就能够将咱们在Flutter上的所有专业知识利用于指标Linux,并且该利用程序运行杰出。与Canonical团队单干是一次很棒的经验。他们热心,投入并热衷于使Flutter不仅针对Linux,而且针对每个平台都变得更好。这是一个了不起的我的项目,我很快乐可能应用Flutter定位另一个次要的操作系统。” —Grant Skinner如果您想在Linux机器上应用Flokk利用,则能够在GitHub上下载最新版本。或者,如果您正在疾速运行,则能够从Snap Store下载Flokk利用。 在Linux上轻松装置Flutter当初,您曾经理解了Flutter在桌面类应用程序(尤其是Linux)上的运行状况,您将心愿使其在本人的Linux机器上运行。为使操作尽可能简略,咱们很快乐在Snap Store中提供Linux版Flutter SDK。 Flutter SDK快照提供了在您喜爱的Linux发行版上开发Flutter应用程序所需的所有。无需装置大量开发依赖项;只需装置Flutter SDK快照和您最喜爱的IDE,便领有了创立,构建和公布Linux应用程序所需的所有。 例如,如果您想开始为Linux开发Flutter应用程序,并且您抉择的IDE是Visual Studio Code,那么这就是您在Linux终端上须要做的所有: $ snap install --classic flutter$ snap install --classic code$ code --install-extension dart-code.flutter如果您还想应用Linux开发挪动应用程序,则能够通过装置Android SDK或Android Studio(包含Android SDK)来实现。无关Flutter SDK的更多信息,请拜访https://snapcraft.io/flutter ...

July 10, 2020 · 1 min · jiezi

Flutter-117-新-Material-motion-规范的预构建动画

老孟导读:在 Flutter 1.17 公布大会上,Flutter 团队还公布了新的 Animations 软件包,该软件包提供了实现新的 Material motion 标准的预构建动画。软件包 pub 地址:https://pub.dev/packages/animations Material motion 标准:https://material.io/design/motion/the-motion-system.html 引入插件,版本号请到 pub 上查看最新版本号: animations: ^1.1.1Container transform容器转换模式设计用于蕴含容器的UI元素之间的转换。此模式在两个UI元素之间创立可见连贯。 案例:构建GridView,点击其中一项时跳转到期详情页面: GridView.builder( padding: EdgeInsets.all(8), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 2, mainAxisSpacing: 4), itemBuilder: (context, index) { return OpenContainer( transitionDuration: _duration, closedBuilder: (BuildContext _, VoidCallback openContainer) { return Container( child: Image.asset( 'assets/images/b.jpg', fit: BoxFit.fitWidth, ), ); }, openBuilder: (BuildContext context, VoidCallback _) { return _DetailPage(); }, ); }, itemCount: 50,)应用 OpenContainer 组件,closedBuilder 示意敞开状态时到组件,在这里示意 GridView Item,openBuilder 示意点击要跳转的页面,这里示意详情页面。 ...

July 9, 2020 · 3 min · jiezi

Flutter-实战动画核心

老孟导读:动画系统是任何一个UI框架的核心功能,也是开发者学习一个UI框架的重中之重,同时也是比较难掌握的一部分,下面我们就一层一层的揭开 Flutter 动画的面纱。任何程序的动画原理都是一样的,即:视觉暂留,视觉暂留又叫视觉暂停,人眼在观察景物时,光信号传入大脑神经,需经过一段短暂的时间,光的作用结束后,视觉形象并不立即消失,这种残留的视觉称“后像”,视觉的这一现象则被称为“视觉暂留”。 人眼能保留0.1-0.4秒左右的图像,所以在 1 秒内看到连续的25张图像,人就会感到画面流畅,而 1 秒内看到连续的多少张图像称为 帧率,即 FPS,理论上 达到 24 FPS 画面比较流畅,而Flutter,理论上可以达到 60 FPS。 AnimationController介绍完了动画系统的基本原理,实现一个蓝色盒子大小从 100 变为 200动画效果: class AnimationBaseDemo extends StatefulWidget { @override _AnimationBaseDemoState createState() => _AnimationBaseDemoState();}class _AnimationBaseDemoState extends State<AnimationBaseDemo> { double _size = 100; @override Widget build(BuildContext context) { return Center( child: GestureDetector( onTap: () { setState(() { _size = 200; }); }, child: Container( height: _size, width: _size, color: Colors.blue, alignment: Alignment.center, child: Text('点我变大',style: TextStyle(color: Colors.white,fontSize: 18),), ), ), ); }} ...

July 7, 2020 · 5 min · jiezi

把会的技能做个汇总NodeJs-后端-Flutter做安卓苹果App-H5端-微信小程序-web端管理后台

突发:想把自己会的知识汇总起来。 如何汇总?1.写一个新的项目,把会的技能都用上2.在sf上记录,并立flag,自我督促 多端同时开发确实累,不过提升还是比较明显的:没有人催赶进度(经常被公司压榨?),遇到问题可以尽可能的寻找最优解,平常不是很熟悉的地方加深印象等等。 实践 技术栈等规划1.后端:NodeJS后端、mongoDB、Redis2.C端:用Flutter做iOS和Android、TaroJS实现微信小程序和H53.管理后台:React实现,Ant-Design UI(毕竟好看)4.运维:docker部署、域名、七牛CDN储存图标、文件等静态资源 首页 通过后台配置不同的资源位,实现首页动态加载。1.后台配置「资源」(图片、标题、点击条转的h5/app路由地址)2.配置「资源位」关联多个「资源」,譬如「banner资源位」,由多个图片资源组成3.配置业务场景,关联多个资源位,譬如「首页场景」,由多个资源位组成:banner资源位、box资源位等等app端与h5端只要请求「首页场景」数据即可。后期拓展:只要在首页开发多个资源位样式即可。个人中心 // TODO社区 // TODO目前进度1.App端目前banner资源位样式、box资源位样式动态加载2.管理后台:从资源 => 资源位 => 业务场景配置、后台用户增删改查、登录3.后端:资源、资源位、业务场景配置增删改查、后台用户体系增删改查4.h5与小程序端暂无进展 后面继续补充,先上个进度图:

July 5, 2020 · 1 min · jiezi

Flutter-应用开发之Bloc模式

基本概念响应式编程所谓响应式编程,指的是一种面向数据流和变化传播的编程范式。使用响应式编程范式,意味着可以在编程语言中更加方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。 响应式编程最初的目的是为了简化交互式用户界面的创建和实时系统动画的绘制而提出来的一种方法,是为了简化MVC软件架构而设计的。在面向对象编程语言中,响应式编程通常以观察者模式的扩展呈现。还可以将响应式流模式和迭代器模式比较,一个主要的区别是,迭代器基于”拉“,而响应式流基于”推“。 使用迭代器是一种命令式编程,由开发者决定何时去访问序列中的next()元素。而在响应式流中,与Iterable-Iterator对应的是Publisher-Subscriber。当新的可用元素出现时,发布者通知订阅者,这种”推“正是响应的关键。此外,应用于推入元素上的操作是声明式的而不是命令式的:程序员要做的是表达计算的逻辑,而不是描述精准的控制流程。 除了推送元素,响应式编程还定义了良好的错误处理和完成通知方式。发布者可以通过调用next()方法推送新的元素给订阅者,也可以通过调用onError()方法发送一个错误信号或者调用onComplete()发送一个完成信号。错误信号和完成信号都会终止序列。 响应式编程非常灵活,它支持没有值、一个值或n个值的用例(包括无限序列),因此现在大量的应用程序开发都悄然使用这种流行的模式进行开发。 Stream在Dart中,Stream和Future是异步编程的两个核心API,主要用于处理异步或者延迟任务等,返回值都是Future对象。不同之处在于,Future用于表示一次异步获得的数据,而Stream则可以通过多次触发成功或失败事件来获取数据或错误异常。 Stream 是 Dart 提供的一种数据流订阅管理工具,功能有点类似于 Android 中的 EventBus 或者 RxBus,Stream 可以接收任何对象,包括另外一个 Stream。在Flutter的Stream流模型中,发布对象通过 StreamController 的 sink来添加数据,然后通过 StreamController 发送给 Stream,而订阅者则通过调用Stream的listen()方法来进行监听,listen()方法会返回一个 StreamSubscription 对象,StreamSubscription 对象支持对数据流进行暂停、恢复和取消等操作。 根据数据流监听器个数的不同,Stream数据流可以分为单订阅流和多订阅流。所谓单订阅流,指的是整个生命周期只允许存在一个监听器,如果该监听器被取消,则不能继续进行监听,使用的场景有文件IO流读取等。而所谓广播订阅流,指的是应用的生命周期内允许有多个监听器,当监听器被添加后就可以对数据流进行监听,此种类型适合需要进行多个监听的场景。 例如,下面是使用Stream的单订阅模式进行数据监听的示例,代码如下。 class StreamPage extends StatefulWidget { StreamPage({Key key}): super(key: key); @override _StreamPageState createState() => _StreamPageState();}class _StreamPageState extends State<StreamPage> { StreamController controller = StreamController(); Sink sink; StreamSubscription subscription; @override void initState() { super.initState(); sink = controller.sink; sink.add('A'); sink.add(1); sink.add({'a': 1, 'b': 2}); subscription = controller.stream.listen((data) => print('listener: $data')); } @override Widget build(BuildContext context) { return Center(); } @override void dispose() { super.dispose(); sink.close(); controller.close(); subscription.cancel(); }}运行上面的代码,会在控制台输出如下日志信息。 ...

July 5, 2020 · 4 min · jiezi

Flutter-中渐变的高级用法

Flutter 中渐变有三种: LinearGradient:线性渐变RadialGradient:放射状渐变SweepGradient:扇形渐变看下原图,下面的渐变都是在此图基础上完成。 LinearGradient给一张图片添加从上到下的线性渐变: ShaderMask( shaderCallback: (Rect bounds) { return LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Colors.red,Colors.blue,Colors.green], ).createShader(bounds); }, blendMode: BlendMode.color, child: Image.asset( 'assets/images/b.jpg', fit: BoxFit.cover, ),) begin 和 end 表示渐变的方向,上面设置的方向是从顶部中间到底部中间。 color 表示渐变的颜色。 设置各个渐变色的结束点: Color color = Colors.orange;return ShaderMask( shaderCallback: (Rect bounds) { return LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [color,color,Colors.transparent,Colors.transparent,color,color], stops: [0,.4,.41,.6,.61,1] ).createShader(bounds); }, blendMode: BlendMode.color, child: Image.asset( 'assets/images/b.jpg', fit: BoxFit.cover, ),);stops 的个数要对应 color。 ...

July 5, 2020 · 2 min · jiezi

FlutterFlare-最有趣用户交互动画没有之一

2019年12月12日,Flutter 在 Flutter Interact '19 上发布了如何使用 Rive 和 Flutter 制作动态可交互的动画经验分享,我看了之后,觉得非常有趣,因此,写了3个小 demo,把它写成文章记录分享给大家。 名词理解首先,我们来理解几个名词,不然后续文章,可能看着有些晕,如下: Flare:是 Flutter 的动画插件名称,完整名称是 flare_flutter 我们要在 pubspec.yaml 文件里引入Rive:是制作 Flare 动画的网站,它既是一个网站也是制作工具,在此网站里有很多用户分享 Flare 动画供我们下载使用、Flare API使用文档、制作 Flare 动画的视频教程(大家也可以通过学习制作自己喜欢的动画)等交互动画预览登录交互动画登录交互动画,包含如下6种动画: idle:无任何操作时的状态(熊的身体会上下浮动和眨眼睛)test:当我们在 email 输入框中输入时的状态(熊会看向输入框,且随着你输入的长度旋转头部)hands_up:当我们在 password 输入框中输入时的状态 (熊会用手蒙上眼睛)hands_down:当我们在 password 输入框输入完成时的状态 (熊会放下双手)fail:当我们登录失败时的状态(熊会做出难过的表情)success:当我们登录成功时的状态(熊会做出高兴的表情)以上6种状态,可以在 Rive 网站查看具体动画,点击进入查看 下面,我们来看看案例里实现动画效果 idle:无任何操作时的状态,如图: test:当我们在 email 输入框中输入时的状态,如图: hands_up:当我们在 password 输入框中输入时的状态,hands_down:当我们在 password 输入框输入完成时的状态,如图: fail:当我们登录失败时的状态,如图: success:当我们登录成功时的状态,如图: Button交互动画button 交互动画,如图: Menu交互动画menu 交互动画,如图: 以上所有动画,也可以 点击观看视频 代码实现如何用代码实现,分为以下2个步骤: 引入插件和资源:引入相关插件 flare_flutter 、 smart_flare编写代码:编写相关代码引入插件和资源引入插件和资源,如下: ...

July 4, 2020 · 2 min · jiezi

MXFlutter基于JS的Flutter框架用JS也能写出Flutter应用

项目名称:MXFlutter项目作者:MXFlutter Team开源许可协议:MIT项目地址:https://gitee.com/huoxd/MXFlu... 项目简介MXFlutter 是一套基于 JavaScript 的 Flutter 框架,可以用极其类似 Dart 的开发方式,通过编写 JavaScript 代码,来开发 Flutter 应用,或者使用 mxjsbuilder 编译器,把现有Flutter 工程编译为JS,运行在 mxflutter 之上。 项目特性支持Dart Flutter语法支持定义Flutter中同名Widget类支持定义相同的Build方式,SetState刷新及事件响应方法支持js模块化开发支持模拟器页面热更新核心思想把 Flutter 的渲染逻辑中的三棵树(即:WidgetTree、Element、RenderObject )中的第一棵(即:WidgetTree),放到 JavaScript 中生成。用 JavaScript 完整实现了 Flutter 控件层封装,可以使用 JavaScript,用极其类似 Dart 的开发方式,开发Flutter应用,利用JavaScript版的轻量级Flutter Runtime,生成UI描述,传递给Dart层的UI引擎,UI引擎把UI描述生产真正的 Flutter 控件。所以,它在iOS上是完全动态化的。 项目结构MXFlutter,就是用JavaScript,以Flutter的写法开发Flutter。具体的项目结构分为三层,请看下图: 1.VM层: MXFlutter Runtime定义和Flutter Widget同名镜像类响应式UI框架2.Flutter层: Script脚本管理模块DSL2Widget UIEngine,事件支持Dart业务API支持内存管理,对象生命周期管理3.Native层: VM虚拟机线程管理Native业务API支持项目效果 UI 展示单页面演示下面是UI截图对应的JS代码,没错,你没有眼花,这个是真的 JavaScript 代码,可以在 MXFlutter 的运行时库上渲染出 Flutter 的UI,(是不是很像Flutter里面的组件代码)! class JSPestoPage extends MXJSWidget { constructor() { super("JSPestoPage"); this.recipes = recipeList; } build(context) { let statusBarHeight = 24; let mq = MediaQuery.of(context); if (mq) { statusBarHeight = mq.padding.top } let w = new Scaffold({ appBar: new AppBar({ title: new Text("Pesto Demo") }), floatingActionButton: new FloatingActionButton({ child: new Icon(new IconData(0xe3c9)), onPressed: function () { }, }), body: new CustomScrollView({ semanticChildCount: this.recipes.length, slivers: [ //this.buildAppBar(context, statusBarHeight), this.buildBody(context, statusBarHeight), ], }), //body:this.buildItems()[0] }); return w; } buildAppBar(context, statusBarHeight) { return SliverAppBar({ pinned: true, expandedHeight: _kAppBarHeight, actions: [ IconButton({ icon: new Icon(new IconData(1)), tooltip: 'Search', onPressed: function () { }, }), ], flexibleSpace: LayoutBuilder({ builder: function (context, constraints) { size = constraints.biggest; appBarHeight = size.height - statusBarHeight; t = (appBarHeight - kToolbarHeight) / (_kAppBarHeight - kToolbarHeight); extraPadding = new Tween({ begin: 10.0, end: 24.0 }).transform(t); logoHeight = appBarHeight - 1.5 * extraPadding; return Padding({ padding: EdgeInsets.only({ top: statusBarHeight + 0.5 * extraPadding, bottom: extraPadding, }), child: Center({ child: new Icon(new IconData(1)) }), }); }, }), }); } buildBody(context, statusBarHeight) { let mediaPadding = EdgeInsets.all(0); let mq = MediaQuery.of(context); if (mq) { mediaPadding = MediaQuery.of(context).padding; } let padding = EdgeInsets.only({ top: 8.0, left: 8.0 + mediaPadding.left, right: 8.0 + mediaPadding.right, bottom: 8.0 }); return new SliverPadding({ padding: padding, sliver: new SliverGrid({ gridDelegate: new SliverGridDelegateWithMaxCrossAxisExtent({ maxCrossAxisExtent: _kRecipePageMaxWidth, crossAxisSpacing: 8.0, mainAxisSpacing: 8.0, }), delegate: new SliverChildBuilderDelegate( function (context, index) { let recipe = this.recipes[index]; let w = new RecipeCard({ recipe: recipe, onTap: function () { showRecipePage(context, recipe); }, }); return w; }, { childCount: this.recipes.length, }), }), }); }如果你想要了解它更详细的使用和接入方法,那么就点击后面的链接前往项目主页看看吧:https://gitee.com/huoxd/MXFlu... ...

July 3, 2020 · 2 min · jiezi

使用-Flutter-快速实现请假与写周报应用

APP 简介公司使用的请假及写周报系统一直都是网页版的,之前我们也有想过出一个移动端版本,但因为一些原因没有付诸行动。刚好最近 LeanCloud 新发布了 Flutter SDK,就决定用 Flutter 来开发这款 APP。 之所以选择 Flutter,主要原因是一份代码可以同时满足 iOS 和 Android 两大平台,这样所有同事都可以享受到这款 APP 带来的便利。 APP 的后端数据全部存放在 LeanCloud,不用担心后端系统的开发维护,实现起来也很简单。 APP 效果预览App Store下载链接,或者 App Store 搜索 LeanCN 下载。 开发环境搭建Flutter 安装和环境搭建直接查看: Flutter 文档。编辑器可以选择 Android Studio、Visual Studio Code 或者 Emacs,编辑器就根据个人喜好和开发习惯选择了。 Flutter 开发环境配置好以后,再来创建 LeanCloud 应用。 首先登录 LeanCloud 控制台,创建一个新应用;在控制台 > 应用 > 设置 >域名绑定页面绑定 API 访问域名。暂时没有域名可以略过这一步,LeanCloud 也提供了短期有效的免费体验域名;或者注册 LeanCloud 国际版,国际版不要求绑定域名。在控制台 > 应用 > 设置 > 应用 Keys 页面记录 AppID、AppKey 与服务器地址备用,这里的服务器地址就是 REST API 服务器地址。如果未绑定域名,控制台相同的位置可以获取到免费的共享域名。 ...

July 2, 2020 · 2 min · jiezi

flutter学习笔记三慕课技术胖老师听课笔记

4-1电影海报实例代码基本结构的建立import 'package:flutter/material.dart';//void是没有返回值的 主方法调用MyApp 所以在此处传递数据void main() => runApp(MyApp());//定义一个widgetclass MyApp extends StatelessWidget { final List<String> items;// 构造方法 默认参数为key主键直接带上 调用父类 MyApp({Key key, @required this.items}) : super(key: key);// 重写build方法 @override// 上下文参数 Widget build(BuildContext context) { return MaterialApp( title: '电影海报实例', home: Scaffold( appBar: AppBar( title: Text('电影海报实例'), ), body: new Text('电影海报实例') ), ); }}4-2电影海报实例代码GridViewWidget学习import 'package:flutter/material.dart';//void是没有返回值的 主方法调用MyApp 所以在此处传递数据void main() => runApp(MyApp());//定义一个widgetclass MyApp extends StatelessWidget { final List<String> items;// 构造方法 默认参数为key主键直接带上 调用父类 MyApp({Key key, @required this.items}) : super(key: key);// 重写build方法 @override// 上下文参数 Widget build(BuildContext context) { return MaterialApp( title: '电影海报实例', home: Scaffold( appBar: AppBar( title: Text('电影海报实例'), ),// 网格GridView.count意思是我们要设置每一行的列数 body: GridView.count(// 内边距 需要调用 EdgeInset组件 padding: const EdgeInsets.all(10.0),// 外边距 crossAxisSpacing: 10.0,// 列数 crossAxisCount: 3, children: <Widget>[ const Text('iloveimooc'), const Text('iloveimooc'), const Text('iloveimooc'), const Text('iloveimooc'), const Text('iloveimooc'), ], )), ); }}4-3 电影海报图片的加入与课程总结import 'package:flutter/material.dart';//void是没有返回值的 主方法调用MyApp 所以在此处传递数据void main() => runApp(MyApp());//定义一个widgetclass MyApp extends StatelessWidget { final List<String> items;// 构造方法 默认参数为key主键直接带上 调用父类 MyApp({Key key, @required this.items}) : super(key: key);// 重写build方法 @override// 上下文参数 Widget build(BuildContext context) { return MaterialApp( title: '电影海报实例', home: Scaffold( appBar: AppBar( title: Text('电影海报实例'), ),// 网格GridView.count意思是我们要设置每一行的列数 body: GridView(//网格的内容 SliverGridDelegateWithFixedCrossAxisCount可以设置列数 gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(// 一行有几列 crossAxisCount: 3,// 外边距 行的间距 mainAxisSpacing: 2.0,// 列之间的间距 crossAxisSpacing: 2.0,// 长宽比 1正方形 宽和长的比 childAspectRatio: .7), children: <Widget>[ new Image.network( 'https://img2.mukewang.com/szimg/5ef018f808c6394c06000338-360-202.jpg', fit: BoxFit.cover), new Image.network( 'https://img1.mukewang.com/szimg/5ee0782708609a8506000338-360-202.jpg', fit: BoxFit.cover), new Image.network( 'https://img1.mukewang.com/szimg/5ed0bbc908af61c706000338-360-202.jpg', fit: BoxFit.cover), new Image.network( 'https://img2.mukewang.com/szimg/5ef018f808c6394c06000338-360-202.jpg', fit: BoxFit.cover), new Image.network( 'https://img1.mukewang.com/szimg/5ee0782708609a8506000338-360-202.jpg', fit: BoxFit.cover), new Image.network( 'https://img1.mukewang.com/szimg/5ed0bbc908af61c706000338-360-202.jpg', fit: BoxFit.cover), new Image.network( 'https://img2.mukewang.com/szimg/5ef018f808c6394c06000338-360-202.jpg', fit: BoxFit.cover), new Image.network( 'https://img1.mukewang.com/szimg/5ee0782708609a8506000338-360-202.jpg', fit: BoxFit.cover), new Image.network( 'https://img1.mukewang.com/szimg/5ed0bbc908af61c706000338-360-202.jpg', fit: BoxFit.cover), ], )), ); }}

July 2, 2020 · 2 min · jiezi

Flutter-vs-Native与ReactNative检查性能

老孟导读:这是老孟翻译的付费文章,文章所有权归原作者所有。欢迎加入老孟Flutter交流群,每周翻译2-3篇付费文章,精彩不容错过。 原文地址:https://medium.com/swlh/flutt... 今天,一些最流行的构建移动应用程序的解决方案是原生开发或者使用React Native或Flutter跨平台方法。虽然原生开发被定位为AAA技术解决方案,但它具有一些缺点,为跨平台应用程序的进入创造了市场空间。总的来说,本机开发需要开发团队付出更多的努力来完成项目,但它可以完全控制棘手的问题。另一方面,如果选择跨平台,则由于具有通用的代码库,因此可以大大加快开发过程,简化项目支持并减少开发费用。 与跨平台开发相比,原生的另一优势是性能。在技术领域,您会遇到“跨平台应用程序运行缓慢”的成见。我们决定测试它是否正确,以及跨平台应用程序比本地应用程序慢的程度。 有不同类型的性能,其中一些是:与电话API交互(访问照片,文件系统,获取GPS位置等)。渲染速度(动画平滑度,更改UI时的每秒帧数或及时发生的某些UI效果)。业务逻辑(数学计算和内存操作的速度。这种性能对于具有复杂业务逻辑的应用最为重要)。在本文中,我们分享了性能测试的结果,这些结果显示了在原生和跨平台方法中实现的数字PI的数学计算。 适用于iOS的CPU密集型测试(Gauss–Legendre算法) iOS: Objective-C是用于iOS开发的最佳编程语言。 Swift比Objective C慢1.7倍惊喜:Flutter比Swift快一点(15%)。React Native比Objective C慢20倍适用于iOS的CPU密集型测试(Borwein算法) iOS: Objective-C是iOS应用开发的最佳选择。 Swift比Objective-C慢1.9倍。Flutter比Swift慢5倍。React Native版本比Swift版本慢15倍以上。适用于Android的CPU密集型测试(Gauss–Legendre算法) Java和Kotlin具有相似的性能指标,并且是Android开发的最佳选择。Flutter比原生慢大约20%。React Native比原生慢15倍。适用于Android的CPU密集型测试(Borwein算法) Java和Kotlin具有相似的性能指标,并且是Android开发的最佳选择。原生速度是Flutter的2倍。React native比原生慢6倍。技术细节:所有测试都在真实的物理设备上完成(iPhone 6s IOS 13.2.3和在Android 9.0下运行的Xiaomi Redmi Note 5);我们评估了发布版本的性能。在某些情况下,调试版本可能比发行版本要慢得多。所有测试都运行了几次,并计算出平均结果。使用了计算Ga值的Gauss–Legendre和Borwein算法。 Pi编号已被计算100次,精度为1000万位数。与Borwein相比,Gauss–Legendre是一种内存密集型算法,但Borwein的CPU密集型。源代码:https://github.com/nazarcybulskij/Mobile_Bechmarks重要要点总之,并非所有跨平台应用程序都运行缓慢。不仅如此,Flutter应用程序的性能要比Swift应用程序高。如果您要开发超快速的iOS应用程序,那么Objective C和Flutter将是明智的选择。对于具有高负载计算的应用程序,Flutter是Android和iOS应用程序开发的不错选择。如果您在选择开发移动工具时遇到麻烦,请随时通知inVerita,我们随时乐意为您提供帮助。 交流老孟Flutter博客地址(330个控件用法):http://laomengit.com 欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:

July 2, 2020 · 1 min · jiezi

Flutter-vs-React-Native-vs-Native深度性能比较

老孟导读:这是老孟翻译的付费文章,文章所有权归原作者所有。欢迎加入老孟Flutter交流群,每周翻译2-3篇付费文章,精彩不容错过。 原文地址:https://medium.com/swlh/flutt... 让我们比较流行的移动开发工具在日常生活中的FPS,CPU,内存和GPU性能。 研究背后的故事inVerita及其移动开发团队不断研究市场上提供的跨平台移动解决方案的性能,以回答哪种技术最适合您的产品,是 Flutter 或 React Native(或 Native)甚至是职业(原文是:maybe even career),这就是 Flutter vs React Native vs Native 第一篇文章出现的原因。是的,这颇有争议,因为有人可以说我们不是每天使用React Native进行多次计算(可能是这种情况),但是在这种情况下,Flutter或Native应用程序可以更好地执行CPU繁重的任务。 因此,在本文中,我们决定研究UI的性能,该性能对日常使用移动应用程序的用户影响更大。 衡量UI性能很复杂,这要求工程师在每个平台上以相同的方式实现相同的功能。我们将 GameBench 作为测试工具,并确保我们保持客观性(这并没有改变我们在很多方面都非常喜欢Flutter的事实:),并且仍在运行许多React Native和Native项目)。 GameBench有很多改进空间,但我们的目标是设法将每个应用程序置于一个测试环境中。 源代码是开放的,因此请尝试并与我们分享您的想法。 UI动画通常在不同平台上使用不同的工具,因此我们将所有内容都缩小到每个平台支持的库中(但只有一种情况),或者至少我们做了能够做到的一切。测试结果可能会有所不同,并且取决于您的实施方法,我们相信您作为特定技术的潜在真正专家可以将您的特定工具集推到极限,使其超过我们的数量,如果您这样做,我们将非常高兴。现在,让我们看一下案例。 硬件信息:为了进行测试,我们使用了价格合理的小米Redmi Note 5和iPhone 6s。 仓库地址https://github.com/InVeritaSoft/Mobile_frameworks_UI-benchmarks 用例1 —列表视图基准我们使用Native,React Native和Flutter在Android和iOS上实现了相同的UI。我们还使用Android上的RecyclerView.SmoothScroller来自动化滚动速度。在iOS和React Native上,我们使用了带有计时器的方法,并以编程方式滚动到位置。在Flutter上,我们使用ScrollController平滑滚动列表。在每种情况下,我们在列表视图中都有1000个项目,并且滚动时间相同以到达最后一个列表元素。在每种情况下,我们都使用每个平台具有不同库的图像缓存。更多细节可以在源代码中揭示。 在这种情况下使用的第三方库:iOS: 加载和缓存图像 — NukeAndroid: 加载和缓存图像 — GlideReact Native: 加载和缓存图像— React-native-fast-image 所有测试均显示出大致相同的FPS。与Flutter和React Native相比,Android Native使用的内存只有一半。React Native需要最多的CPU开发。原因是在JS和本机代码之间使用JSBridge,这会导致序列化和反序列化方面的资源浪费。关于电池开发,Android Native具有最佳效果。 React-native落后于Android和Flutter。运行连续动画会在React Native上消耗更多电池电量。iPhone 6s test FPS,React Native的结果比Flutter和Swift差。原因是无法在iOS上使用IoT编译。内存。 Flutter与Native在内存消耗上几乎一样,但在CPU上仍然较重。在此测试中,React Native远远落后于Flutter和native。Flutter和Swift之间的区别。当iOS Native积极使用GPU时,Flutter积极使用CPU。 Flutter中的协调会增加CPU的负载。用例2 —繁重的动画测试如今,大多数在Android和iOS上运行的手机都具有强大的硬件。在大多数情况下,使用常规的商业应用程序时,不会发现fps下降。因此,我们决定对重型动画进行一些测试。重得足以导致fps下降。我们使用了在Android,iOS,React Native上使用Lottie进行动画处理的矢量动画,并在Flutter上使用了与Flare相同的动画。 Android,iOS,React Native 使用 Lottie 动画,Flutter 使用 Flare。 ...

July 2, 2020 · 1 min · jiezi

Flutter-vs-React-Native-vs-Native深度性能比较

老孟导读:这是老孟翻译的付费文章,文章所有权归原作者所有。欢迎加入老孟Flutter交流群,每周翻译2-3篇付费文章,精彩不容错过。 原文地址:https://medium.com/swlh/flutt... 让我们比较流行的移动开发工具在日常生活中的FPS,CPU,内存和GPU性能。 研究背后的故事inVerita及其移动开发团队不断研究市场上提供的跨平台移动解决方案的性能,以回答哪种技术最适合您的产品,是 Flutter 或 React Native(或 Native)甚至是职业(原文是:maybe even career),这就是 Flutter vs React Native vs Native 第一篇文章出现的原因。是的,这颇有争议,因为有人可以说我们不是每天使用React Native进行多次计算(可能是这种情况),但是在这种情况下,Flutter或Native应用程序可以更好地执行CPU繁重的任务。 因此,在本文中,我们决定研究UI的性能,该性能对日常使用移动应用程序的用户影响更大。 衡量UI性能很复杂,这要求工程师在每个平台上以相同的方式实现相同的功能。我们将 GameBench 作为测试工具,并确保我们保持客观性(这并没有改变我们在很多方面都非常喜欢Flutter的事实:),并且仍在运行许多React Native和Native项目)。 GameBench有很多改进空间,但我们的目标是设法将每个应用程序置于一个测试环境中。 源代码是开放的,因此请尝试并与我们分享您的想法。 UI动画通常在不同平台上使用不同的工具,因此我们将所有内容都缩小到每个平台支持的库中(但只有一种情况),或者至少我们做了能够做到的一切。测试结果可能会有所不同,并且取决于您的实施方法,我们相信您作为特定技术的潜在真正专家可以将您的特定工具集推到极限,使其超过我们的数量,如果您这样做,我们将非常高兴。现在,让我们看一下案例。 硬件信息:为了进行测试,我们使用了价格合理的小米Redmi Note 5和iPhone 6s。 仓库地址https://github.com/InVeritaSoft/Mobile_frameworks_UI-benchmarks 用例1 —列表视图基准我们使用Native,React Native和Flutter在Android和iOS上实现了相同的UI。我们还使用Android上的RecyclerView.SmoothScroller来自动化滚动速度。在iOS和React Native上,我们使用了带有计时器的方法,并以编程方式滚动到位置。在Flutter上,我们使用ScrollController平滑滚动列表。在每种情况下,我们在列表视图中都有1000个项目,并且滚动时间相同以到达最后一个列表元素。在每种情况下,我们都使用每个平台具有不同库的图像缓存。更多细节可以在源代码中揭示。 在这种情况下使用的第三方库:iOS: 加载和缓存图像 — NukeAndroid: 加载和缓存图像 — GlideReact Native: 加载和缓存图像— React-native-fast-image 所有测试均显示出大致相同的FPS。与Flutter和React Native相比,Android Native使用的内存只有一半。React Native需要最多的CPU开发。原因是在JS和本机代码之间使用JSBridge,这会导致序列化和反序列化方面的资源浪费。关于电池开发,Android Native具有最佳效果。 React-native落后于Android和Flutter。运行连续动画会在React Native上消耗更多电池电量。iPhone 6s test FPS,React Native的结果比Flutter和Swift差。原因是无法在iOS上使用IoT编译。内存。 Flutter与Native在内存消耗上几乎一样,但在CPU上仍然较重。在此测试中,React Native远远落后于Flutter和native。Flutter和Swift之间的区别。当iOS Native积极使用GPU时,Flutter积极使用CPU。 Flutter中的协调会增加CPU的负载。用例2 —繁重的动画测试如今,大多数在Android和iOS上运行的手机都具有强大的硬件。在大多数情况下,使用常规的商业应用程序时,不会发现fps下降。因此,我们决定对重型动画进行一些测试。重得足以导致fps下降。我们使用了在Android,iOS,React Native上使用Lottie进行动画处理的矢量动画,并在Flutter上使用了与Flare相同的动画。 Android,iOS,React Native 使用 Lottie 动画,Flutter 使用 Flare。 ...

July 2, 2020 · 1 min · jiezi

flutter学习笔记二慕课技术胖老师听课笔记

3-4ImageWidget图片组件讲解import 'package:flutter/material.dart';void main() => runApp(MyApp());//Image.asset:加载资源图片,会使打包时包体过大//Image.network:网络资源图片,经常换的或者动态的图片//image.file:本地图片,比如相机照像后的图片预览//image.memory:加载到内存中的图片,Uint8Listclass MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'TextWidget', home: Scaffold( appBar: AppBar(title: Text('TextWidget')), body: Center( child: Container( child: new Image.network( 'https://img1.mukewang.com/szimg/5ef018f808c6394c06000338-360-202.jpg',// 缩放 值越大图片越小 scale: 1.5,// 图片充满容器 有可能被拉伸// fit: BoxFit.fill,// 图片保持原比例 宽或高最大// fit: BoxFit.contain,// 图片可能被裁切 充满容器 保持原比例 工作中非常实用 fitWidth:横向是充满的纵向可能被裁切或拉伸 fitHeight scaleDown:图片大于容器// fit: BoxFit.cover,// 图片混合模式美工会给 // color: Colors.amber,// colorBlendMode: BlendMode.colorBurn,// 图片重复 repeatX横向Y纵向 repeat: ImageRepeat.repeat, ), width: 300.0, height: 200.0, color: Colors.amber, )), ), ); }}3-5ListViewWidget列表组件讲解1.列表瓦片import 'package:flutter/material.dart';//void是没有返回值的void main() => runApp(MyApp());//定义一个widgetclass MyApp extends StatelessWidget {// 重写build方法 @override// 上下文参数 Widget build(BuildContext context) { return MaterialApp( title: 'TextWidget', home: Scaffold( appBar: AppBar(title: Text('TextWidget')), body: new ListView(// 返回的是一个数组 children: <Widget>[// 列表瓦片 new ListTile(// 最主要的 flutter提供给我们的icon组件 leading: new Icon(Icons.accessibility),// 图标加文字 title: new Text( 'border_right', ), ), new ListTile(// 最主要的 flutter提供给我们的icon组件 leading: new Icon(Icons.accessibility),// 图标加文字 title: new Text( 'border_right', ), ), new ListTile(// 最主要的 flutter提供给我们的icon组件 leading: new Icon(Icons.repeat),// 图标加文字 title: new Text( 'border_right', ), ), new ListTile(// 最主要的 flutter提供给我们的icon组件 leading: new Icon(Icons.access_alarm),// 图标加文字 title: new Text( 'border_right', ), ) ], )), ); }}2.图片列表import 'package:flutter/material.dart';//void是没有返回值的void main() => runApp(MyApp());//定义一个widgetclass MyApp extends StatelessWidget {// 重写build方法 @override// 上下文参数 Widget build(BuildContext context) { return MaterialApp( title: 'TextWidget', home: Scaffold( appBar: AppBar(title: Text('TextWidget')), body: new ListView(// 返回的是一个数组 children: <Widget>[ new Image.network( 'https://img1.mukewang.com/szimg/5ee0782708609a8506000338-360-202.jpg'), new Image.network( 'https://img1.mukewang.com/szimg/5ed0dcff0984b5c812000676-360-202.png'), new Image.network( 'https://img1.mukewang.com/szimg/5ee0782708609a8506000338-360-202.jpg'), ], )), ); }}3-6横向列表的使用1.横向列表原始代码import 'package:flutter/material.dart';//void是没有返回值的void main() => runApp(MyApp());//定义一个widgetclass MyApp extends StatelessWidget {// 重写build方法 @override// 上下文参数 Widget build(BuildContext context) { return MaterialApp( title: 'TextWidget', home: Scaffold( appBar: AppBar(title: Text('TextWidget')), body: Center( child: Container( height: 200.0, child: new ListView(// 横向滚动 scrollDirection: Axis.horizontal, children: <Widget>[ new Container( width: 180.0, color: Colors.amber, ), new Container( width: 180.0, color: Colors.purple, ), new Container( width: 180.0, color: Colors.lightGreen, ), new Container( width: 180.0, color: Colors.black12, ), ], ), ), )), ); }}2横向列表优化代码import 'package:flutter/material.dart';//void是没有返回值的void main() => runApp(MyApp());//定义一个widgetclass MyApp extends StatelessWidget {// 重写build方法 @override// 上下文参数 Widget build(BuildContext context) { return MaterialApp( title: 'TextWidget', home: Scaffold( appBar: AppBar(title: Text('TextWidget')), body: Center( child: Container( height: 200.0,// 调用mylist组件 child: Mylist()), )), ); }}//mylist组件分解出来class Mylist extends StatelessWidget { @override Widget build(BuildContext context) { return ListView( // 横向滚动 scrollDirection: Axis.horizontal, children: <Widget>[ new Container( width: 180.0, color: Colors.amber, ), new Container( width: 180.0, color: Colors.purple, ), new Container( width: 180.0, color: Colors.lightGreen, ), new Container( width: 180.0, color: Colors.black12, ), ], ); }}3-7动态列表的使用import 'package:flutter/material.dart';//void是没有返回值的 主方法调用MyApp 所以在此处传递数据void main() => runApp(MyApp(// List()非固定长度 List(3)长度为3 List<String>()指定类型 [1,2,3]直接赋值 $i下标//generate生成器 有两个参数1.是声明长度 (i)每一个循环的参数 单个循环的内容 items: new List<String>.generate(1000, (i) => 'item $i')));//定义一个widgetclass MyApp extends StatelessWidget { final List<String> items;// 构造方法 默认参数为key主键直接带上 调用父类 MyApp({Key key, @required this.items}) : super(key: key);// 重写build方法 @override// 上下文参数 Widget build(BuildContext context) { return MaterialApp( title: 'TextWidget', home: Scaffold( appBar: AppBar(title: Text('TextWidget')), body: new ListView.builder( itemCount: items.length,// 上下文和索引 itemBuilder: (context, index) { return new ListTile(title: new Text('${items[index]}')); }, )), ); }}

July 1, 2020 · 3 min · jiezi

flutter学习笔记一慕课技术胖老师听课笔记

2-5写一个HelloWorld程序Flutter upgrade:cmd控制台中运行Flutter upgrade,升级flutterSDKFlutter doctor 查看flutterSDK版本flutter中的快捷键r:点击后热加载,直接查看预览效果p:在虚拟机中显示网格o:切换Android和iOS的预览模式q:退出调试预览模式 //谷歌推出的扁平化样式 大气美观import 'package:flutter/material.dart';//入口文件void main() => runApp(MyApp());//定义MyApp函数 继承静态的组件class MyApp extends StatelessWidget {// 重写build方法 @override// 返回一个组件 传递一个上下文 Widget build(BuildContext context) { return new MaterialApp( title: "welcome to flutter", home: new Scaffold( appBar: new AppBar( title: new Text("Hello Worldtitle"), ), body: new Center( child: new Text("Hello Worldbody"), ), ), ); }}3-1节TextWidget文本组件import 'package:flutter/material.dart';void main() => runApp(MyApp());//静态组建class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'TextWidget', home: Scaffold( appBar: AppBar(title: Text('TextWidget')), body: Center( child: Text( 'Flutter一切皆组件。Flutter一切皆组件。Flutter一切皆组件。Flutter一切皆组件。Flutter一切皆组件。',// 居中对齐 left right start end(后两个工作不常用 和left right类似 运行效果差不多) textAlign: TextAlign.center,// 最大行数 maxLines: 1,// 默认值 直接把文本截断// overflow: TextOverflow.clip,// 超出省略号 fade不常用 逐行颜色透明度减淡 overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 25.0, color: Color.fromARGB(255, 255, 150, 150),// 下划线实线 decorationStyle: TextDecorationStyle.solid, decoration: TextDecoration.underline), )), ), ); }}3-2节ContainerWidget容器组件-1import 'package:flutter/material.dart';void main() => runApp(MyApp());//静态组建class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'TextWidget', home: Scaffold( appBar: AppBar(title: Text('TextWidget')), body: Center( child: Container( child: new Text( 'Hello Imooc', style: TextStyle(fontSize: 40.0), ),// 底部居左对齐 第一个值为垂直方向 第二个值为水平方向// alignment: Alignment.bottomLeft, // 垂直居中水平向左对齐 alignment: Alignment.centerLeft,// 宽高颜色 width: 500.0, height: 400.0, color: Colors.lightBlue, )), ), ); }}3-3节 ContainerWidget容器组件-2import 'package:flutter/material.dart';void main() => runApp(MyApp());//静态组建class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'TextWidget', home: Scaffold( appBar: AppBar(title: Text('TextWidget')), body: Center( child: Container( child: new Text( 'Hello Imooc', style: TextStyle(fontSize: 40.0), ), alignment: Alignment.bottomLeft, width: 500.0, height: 400.0,// 内边距20// padding:const EdgeInsets.all(20.0),// 分别设置上下左右的边距 padding: const EdgeInsets.fromLTRB(10.0, 0, 0, 59.0),// 外边距 margin: const EdgeInsets.all(10.0), decoration: new BoxDecoration( gradient: const LinearGradient( colors: [Colors.lightGreen, Colors.purple, Colors.amber]), ), )), ), ); }}

July 1, 2020 · 2 min · jiezi

Flutter-实战简约而不简单的计算器

老孟导读:这是 【Flutter 实战】组件系列文章的最后一篇,其他组件地址:http://laomengit.com/guide/widgets/Text.html,接下来将会讲解动画系列,关注老孟,精彩不断。先看一下效果: 大家学习UI编程语言时喜欢用哪个 App 当作第一个练手的项目呢?,我喜欢使用 计算器 ,可能是习惯了吧,学习 Android 和 React Native 都用此 App 当作练手的项目。 下面我会一步一步的教大家如何实现此项目。 整个项目的 UI 分为两大部分,一部分是顶部显示数字和计算结果,另一部分是底部的输入按钮。 所以整体布局使用 Column,在不同分辨率的手机上,规定底部固定大小,剩余空间都由顶部组件填充,所以顶部组件使用 Expanded 扩充,代码如下: Container( padding: EdgeInsets.symmetric(horizontal: 18), child: Column( children: <Widget>[ Expanded( child: Container( alignment: Alignment.bottomRight, padding: EdgeInsets.only(right: 10), child: Text( '$_text', maxLines: 1, style: TextStyle( color: Colors.white, fontSize: 48, fontWeight: FontWeight.w400), ), ), ), SizedBox( height: 20, ), _CalculatorKeyboard( onValueChange: _onValueChange, ), SizedBox( height: 80, ) ], ),)SizedBox 组件用于两个组件之间的间隔。 ...

July 1, 2020 · 3 min · jiezi

FutureBuilder-and-StreamBuilder-优雅的构建高质量项目

本篇文章将介绍从 setState 开始,到 futureBuilder 、 streamBuilder 来优雅的构建你的高质量项目,而不引发 setState 带来的副作用,如对文章感兴趣,请 点击查看源码。 基础的setState更新数据首先,我们使用基础的 StatefulWidget 来创建页面,如下: class BaseStatefulDemo extends StatefulWidget { @override _BaseStatefulDemoState createState() => _BaseStatefulDemoState();}class _BaseStatefulDemoState extends State<BaseStatefulDemo> { @override Widget build(BuildContext context) { return Container(); }}然后,我们使用 Future 来创建一些数据,来模拟网络请求,如下: Future<List<String>> _getListData() async { await Future.delayed(Duration(seconds: 1)); // 1秒之后返回数据 return List<String>.generate(10, (index) => '$index content'); }在 initState() 方法中调用 _getListData() 来初始化数据,如下: List<String> _pageData = List<String>(); @override void initState() { _getListData().then((data) => setState(() { _pageData = data; })); super.initState(); }使用 ListView.builder 来处理这些数据构建UI,如下: ...

June 30, 2020 · 5 min · jiezi

一文看完阿里巴巴-AliFlutter-客户端研发体系

简介: Flutter 是开源的 UI 工具包,其能够帮助开发者通过一套代码库高效构建多平台精美应用,支持移动、Web、桌面和嵌入式平台。Flutter 组件采用现代响应式框架构建,中心思想是用组件 (widget) 构建 UI。淘宝终端技术部无线技术专家王康从 Flutter 的原理出发,介绍了 Flutter 的原理、业内现状,以及阿里巴巴在 Flutter 上所做的深度实践和探索。 一 Flutter 原理Flutter 主要有四个特点:美观、高效、高性能、开放。 美观:Flutter 提供了丰富的 Widget,比如动画、手势等。Flutter 采用了组合式 API 模式,因此为 UI 创建带来了更强的灵活性。此外,Flutter 使用了游戏引擎的方式来写 APP,使得用户可以具有很强的灵活性,能够在像素级别进行控制。高效:Flutter 类似于安卓小系统,使得其能够使用一套代码运行在各种各样的平台之上。此外,在 Debug 模式下还支持热重载,使其能够达到高效的研发效率。高性能:在 Release 模式下,Flutter 是预先编译成机器码,执行期具有高性能。开放:Flutter 是一个开源的项目,基本所有工作都可以在 GitHub 上看到。 以上四个特点的背后就是 Flutter 的原理。首先,Flutter 架构在 OS 之上,最底下是与平台相关的 Embedder 层,其主要负责的工作是 Surface、Thread 以及 Event Loop。在 Embedder 层之上是 Engine,主要包括三部分,Dart Runtime;负责将 UI 绘制到 Surface 上的 Skia,负责文本绘制的 Text。在 Engine 之上就是大家所熟知的 Dart 的 Framework。基于上述这些,开发者即可开发应用。 ...

June 29, 2020 · 2 min · jiezi

Flutter实战自定义滚动条

老孟导读:【Flutter实战】系列文章地址:http://laomengit.com/guide/introduction/mobile_system.html默认情况下,Flutter 的滚动组件(比如 ListView)没有显示滚动条,使用 Scrollbar 显示滚动条: Scrollbar( child: ListView.builder( reverse: false, itemBuilder: (BuildContext context, int index) { return Card( child: Container( height: 45, alignment: Alignment.center, child: Text('$index'), ), ); }, itemCount: 30, itemExtent: 50, ),) 在滑动的过程中,右侧显示滚动条,然而 Scrollbar 无法实现自定义滚动条的样式,比如实现如下滚动条样式, 这时需要自定义一个滚动条组件。 实现自定义滚动条组件首先需要监听滚动组件 滚动的位置,使用 NotificationListener 监听滚动的位置: bool _handleScrollNotification(ScrollNotification notification) { final ScrollMetrics metrics = notification.metrics; print('滚动组件最大滚动距离:${metrics.maxScrollExtent}'); print('当前滚动位置:${metrics.pixels}'); return true; } @override Widget build(BuildContext context) { return NotificationListener<ScrollNotification>( onNotification: _handleScrollNotification, child: ListView.builder( reverse: false, itemBuilder: (BuildContext context, int index) { return Card( child: Container( height: 45, alignment: Alignment.center, child: Text('$index'), ), ); }, itemCount: 30, itemExtent: 50, ), ); }通过 ScrollNotification 获取当前滚动组件最大滚动距离和当前滚动位置,其中 metrics.maxScrollExtent 表示当前滚动组件最大滚动距离,metrics.pixels 表示当前滚动位置。 ...

June 29, 2020 · 2 min · jiezi

从0开始设计Flutter独立APP-第二篇-完整的国际化语言支持

鉴于Flutter高性能渲染和跨平台的优势,闪点清单在移动端APP上,使用了完整的Flutter框架来开发。既然是完整APP,架构搭建完全不受历史Native APP的影响,没有历史包袱的沉淀,设计也能更灵活和健壮。国际化语言的支持,是很多APP都有的一个强需求,APP无论大小,只要还不想放弃国外的客户,一般就需要支持国际化。 官方支持Flutter官方方案提供了国际化的基础支持,如Flutter内置组件的国际化、语言代理、Widget使用语言包、语言设置回调等,并支持自定义第三方类来扩展,可以参考Flutter国际化文档。官方支持代码示例: class DemoLocalizations { DemoLocalizations(this.locale); final Locale locale; static DemoLocalizations of(BuildContext context) { return Localizations.of<DemoLocalizations>(context, DemoLocalizations); } static Map<String, Map<String, String>> _localizedValues = { 'en': { 'title': 'Hello World', }, 'es': { 'title': 'Hola Mundo', }, }; String get title { return _localizedValues[locale.languageCode]['title']; }}官方方案的缺陷官方的支持有几个缺陷: 依赖于BuildContext对象,在非Widget中调用时,需要层层传递BuildContext对象,或存储全局BuildContext对象。在MaterialApp初始化前无法使用国际化(原因也是依赖于BuildContext对象)。语言包定义推荐使用Map方式,无法利用静态语言的优势(语法提示、错误检查等);而为语言包每个属性自定义类和类字段,成本较高、使用和更新灵活性差。i18n介绍鉴于Flutter官方支持的缺陷,我们调研了很多第三方库,最终发现了i18n,并在此基础上、结合Flutter官方支持和自身封装,实现了更灵活易用的方案。 基础使用i18n使用yaml格式来定义语言包,同时提供构建脚本一键生成Dart语言包Class。如下: lib/messages.i18n.yamlbutton: save: Save load: Loadusers: welcome(String name): "Hello $name!" logout: Logout该配置会生成几个Class:Messages、ButtonMessages、UserMessages,生成后的Dart文件使用方式如下: Messages m = Messages();debugPrint(m.users.logout);debugPrint(m.users.welcome('World'));生成的Dart文件预览(开发时无需关心): class Messages { const Messages(); ButtonMessages get button => ButtonExampleMessages(this); UsersMessages get users => UsersExampleMessages(this);}class ButtonMessages { final Messages _parent; const ButtonMessages(this._parent); String get save => "Save"; String get load => "Load";}class UsersMessages { final Messages _parent; const UsersMessages(this._parent); String get logout => "Logout"; String welcome(String name) => "Hello $name!";}进阶功能下面讲解一些进阶用法。 ...

June 28, 2020 · 1 min · jiezi

美团外卖Flutter动态化实践

一、前言Flutter 跨端技术一经推出便在业内赢得了不错的口碑,它在“多端一致”和“渲染性能”上的优势让其他跨端方案很难比拟。虽然 Flutter 的成长曲线和未来前景看起来都很好,但不可否认的是,目前 Flutter 仍处在发展阶段,很多大型互联网企业都无法毫无顾虑地让全线 App 接入,而其中最主要的顾虑是包大小与动态化。 动态化代表着更短的需求上线路径,代表着大大压缩了原始包的大小,从而获得更高的用户下载意向,也代表着更健全的线上质量维护体系。当明白这些意义后,我们也就不难理解,在 Flutter 的应用与适配趋近完善时,动态化自然就成为了一个无法避开的话题。RN 和 Weex 等成熟技术甚至让大家认为动态化是跨端技术的标配。 美团外卖 MTFlutter 团队从 2019 年 9 月开始对动态化进行研究,目前已在多个业务模块上线,内部项目代号 “Flap” 。。 二、Flap 的特点与优势Flap 研发的初心是为了提供一个完整解决方案,而不是一个过渡方案。项目组思考了当下最痛的点并逐一列出,然后再根据目标来做具体选型。在前期,只有需求考虑得越周全,后续的架构和研发才会越明确。在研发过程中,团队应该坚守底线,坚守初心,不断攻克困难,完成昔日定下的目标。 2.1 核心目标通用性,保持 Flutter 多平台支持的能力且方案无平台差异。低成本,动态化对齐 Flutter 生态和常规开发习惯,且可低成本转化现有的 Flutter 页面。适用性,避免包过大、不稳定等不利于应用的缺陷。高性能,保留 Flutter 渲染性能极佳的特点。2.2 动态化选型a. 产物替换 选型中首先考虑到的是下发产物替换,官方在也曾经推出了 Code Push 方案,甚至可以支持 Diff 差量下载,但是在 2019 年 4 月被叫停,这里引用一下官方的发言 Flutter/issues/14330: To comply with our understanding of store policies on Android and iOS, any solution would be limited to JIT code on Android and interpreted code on iOS. We are not confident that the performance characteristics of such a solution on iOS would reach the quality that we demand of our product. (In other words, "it would be too slow".)There are some serious security concerns. Since these patches would essentially allow arbitrary code execution, they would be extremely attractive malware vectors. We could mitigate this by requiring that patches be signed using the same key as the original package, but this is error prone and any mistake would have serious consequences. This is, fundamentally, the same problem that has plagued platforms that allow execution of code from third-party sources. This problem could be mitigated by integrating with a platform update mechanism, but this defeats the purpose of an out-of-band patching mechanism. ...

June 26, 2020 · 7 min · jiezi

谈谈我对-Flutter-未来发展-和-嵌套地狱-的浅显看法

Flutter 未来发展提到 Flutter 就不得不提到 Fuchsia 系统,这是一个尚未正式发布的操作的系统,引用 Android 和 Chrome 的高级副总裁 Hiroshi Lockheimer 在一档播客节目中对 Fuchsia 的介绍是: 不仅仅是手机和个人电脑,在物联网的世界里,越来越多的设备需要操作系统、新的软件运行环境等支持。我认为,在具有不同优势和专业化的诸多操作系统中还存在很大的发展空间。Fuchsia 就是其中之一,所以,请继续保持关注。是的,Fuchsia 系统是为物联网研发的操作系统,物联网简称 IoT,现在全世界都在押注 IoT,包括华为、小米等国内公司。 那 Flutter 和 Fuchsia 又有什么关系呢? Flutter 是 Fuchsia 官方指定的唯一UI开发框架。 现在有很多物联网操作系统 ,Fuchsia 就一定可以脱颖而出吗? 不一定,未来的事情谁说的准呢,但在我看来 Fuchsia 是最有可能发展起来的物联网操作系统,因为一个操作系统的发展除了本身优秀以外,最大的阻碍其实是生态,而 Fuchsia 在生态方面具有天然的优势, 国外的一篇报道曾说: Google 希望将 Android App 无缝移植到 Fuchsia 上,而且一直在做相关工作。试想一下,一旦 Google 将 Android App 无缝移植到 Fuchsia 上,其他物联网操作系统如何与之抗衡。 这里引用 Google 公众号底部的一句话送给大家: 预测未来不如创造未来 在跨平台技术上 Flutter 还有很多竞争对手,比如 HTML5、React Native、Weex、快应用、小程序等,我曾在[跨平台技术发展简介]() 中详细说明了各个跨平台技术的发展历史及优缺点。 Flutter 的出现会终结其他跨平台技术?我想不会的, React Native 发展了这么多年也没有完全干掉 HTML5,应为 HTML5 有其独特的应用场景,比如 营销活动场景、新闻或者博客详情页面等,这些场景非常适合 HTML5。因此 Flutter 也不可能终结其他跨平台技术,总结一句话就是: ...

June 23, 2020 · 3 min · jiezi

Flutter-新闻客户端-02-设计稿适配加入图片字体资源欢迎界面

B站视频https://www.bilibili.com/vide... 本节目标加入图片资源加入字体资源设计稿适配编写界面代码的逻辑和组织1 加入图片资源1.1 flutter 图片资源规则官方说明https://flutter.dev/docs/deve... 按这个规则编排,flutter 自动适配分辨率图片 assets 目录 yaml 配置assets: - assets/images/代码调用Image.asset("assets/images/logo.png")1.2 蓝湖切图 注意选着下 ios 目标,这样会自动切图 1x 2x 3x 三种格式 2 加入字体资源官方说明https://flutter.dev/docs/cook... assets 目录 只上传用到的 ttf 字体,这样能控制打包大小 yaml 配置fonts: - family: Avenir fonts: - asset: assets/fonts/Avenir-Book.ttf weight: 400 - family: Montserrat fonts: - asset: assets/fonts/Montserrat-SemiBold.ttf weight: 600代码调用 3 编写欢迎界面3.1 从上到下、从左到右、由大到小 3.2 设计稿适配插件 flutter_screenutil https://pub.flutter-io.cn/pac... 按设计稿比例适配 3.3 工具函数 screen.dart 设计稿适配函数import 'package:flutter_screenutil/flutter_screenutil.dart';/// 设置宽度double duSetWidth(double width) { return ScreenUtil().setWidth(width);}/// 设置宽度double duSetHeight(double height) { return ScreenUtil().setHeight(height);}/// 设置字体尺寸double duSetFontSize(double fontSize) { return ScreenUtil().setSp(fontSize);}utils.dart 导出类库library utils;export 'screen.dart';3.4 常量配置 ...

June 23, 2020 · 1 min · jiezi

Flutter实战定位装饰权重组件及柱状图案例

老孟导读:Flutter中有这么一类组件,用于定位、装饰、控制子组件,比如 Container (定位、装饰)、Expanded (扩展)、SizedBox (固定尺寸)、AspectRatio (宽高比)、FractionallySizedBox (占父组件比例)。这些组件的使用频率非常高,下面一一介绍,最后给出项目中实际案例熟悉其用法。【Flutter实战】系列文章地址:http://laomengit.com/guide/introduction/mobile_system.htmlContainerContainer 是最常用的组件之一,它是单容器类组件,即仅能包含一个子组件,用于装饰和定位子组件,例如设置背景颜色、形状等。 最简单的用法如下: Container( child: Text('老孟'), )子组件不会发生任何外观上的变化: 设置背景颜色: Container( color: Colors.blue, child: Text('老孟'),) 设置内边距( padding ) 和 外边距( margin ) Container( color: Colors.blue, child: Container( margin: EdgeInsets.all(10), padding: EdgeInsets.all(20), color: Colors.red, child: Text('老孟'), ), )效果如下: decoration 属性设置子组件的背景颜色、形状等。设置背景为圆形,颜色为蓝色: Container( child: Text('老孟,专注分享Flutter技术及应用'), decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.blue),) 默认情况下,圆形的直径等于 Container 窄边长度,相当于在矩形内绘制内切圆。 上面的情况明显不是我们希望看到了,希望背景是圆角矩形: Container( child: Text('老孟,专注分享Flutter技术及应用'), padding: EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( shape: BoxShape.rectangle, borderRadius: BorderRadius.all(Radius.circular(20)), color: Colors.blue), ) ...

June 22, 2020 · 6 min · jiezi

从0开始设计Flutter独立APP-第一篇-数据库与状态管理

鉴于Flutter高性能渲染和跨平台的优势,闪点清单在移动端APP上,使用了完整的Flutter框架来开发。既然是完整APP,架构搭建完全不受历史Native APP的影响,没有历史包袱的沉淀,设计也能更灵活和健壮。 首先列举部分闪点清单的业务特性(较为通用的业务特性): 本地有较大数据量的清单数据,离线可用,未登录可用;登录后需要服务器数据同步状态变更场景多,前端状态逻辑较为复杂,跨页面、跨组件状态更新频繁这几个业务点,设计到的技术选型有:本地数据库、前端状态管理,对很多业务来说,这几点都是比较核心的东西,也是我们今天重点要讲的内容。 数据库选型数据库选型,首先要定的,就是选择数据库类型:关系型数据库、非关系型数据库还是Key/Value存储。 对于关系型数据库,可选的有比如:SQLite、Core Data、GreenDao等;对于非关系型数据库,可选有Realm、UnQLite等;对于Key/Value存储,有比如Redis、Berkeley DB、Level DB等。 由于业务形态具有复杂的查询场景,所以首先排除了Key/Value存储;然后鉴于业务迭代频繁,数据结构变动较大,所以完全的关系型数据库使用成本会较高,版本更新时在数据兼容和数据清洗方面要做较多的工作;所以我们采用了NoSQL数据库,或者支持JSON类型的关系型数据库。 Flutter目前在NoSQL上的可选项并不多,Realm、UnQLite等均未支持(当然可以通过Flutter FFI来封装给Dart用,但成本过高);Flutter的sqflite插件可以较好地支持SQLite,但由于SQLite在3.9以后才支持JSON数据,考虑到Android版本(Android各版本使用的SQLite版本文档)兼容问题,我们并没有采用sqflite;我们最终采用的数据库是Sembast,一个还比较小众,但性能和API建设都还不错的NoSQL数据库。 Sembast介绍 Sembast API很简洁,但能支持较复杂的数据库操作。在数据查询上,能够通过简单的逻辑API,通过聚合构造出复杂的逻辑查询语句;数据排序实现也比较完整,支持多字段排序(但不支持bool类型排序);对事务操作也有支持;支持整型自增key。 Sembast部分API预览 var store = intMapStoreFactory.store('animals');// 事务处理await db.transaction((txn) async { await store.add(txn, {'name': 'fish'}); await store.add(txn, {'name': 'cat'}); await store.add(txn, {'name': 'dog'});});// 数据查询var finder = Finder( filter: Filter.greaterThan('name', 'cat'), sortOrders: [SortOrder('name')]);var records = await store.find(db, finder: finder);expect(records.length, 2);expect(records[0]['name'], 'dog');expect(records[1]['name'], 'fish');但由于对小众数据库前途的担忧考虑,我们设计了便于迁移的数据架构,对数据操作层做了一层抽象,后期如果迁移数据库,业务层可以完全不需要改动。 状态管理选型状态管理,在如今的前端技术中,是非常重要的一环,好的状态管理框架,可以让业务更好得解耦、简化组件数据通讯成本、大幅提升开发体验。我们在状态管理选型上花了较多的时间来对比各种方案,比如:provider、bloc、redux、scoped_model、mobx、甚至业界网红团队的fish-redux。我们最终采用的是mobx,关于各个方案的对比,一篇文章讲不完,我们最终选择mobx,更多是因为它的API更友好。 Mobx采用注解的方式来定义状态,并封装了一个Widget用于Widget的数据更新,学习、使用成本较低。 注解定义Mobx的注解使用方式,与Web中的Vue非常类似如: 使用@observable来注解一个属性,表示其需要被监听,Mobx会自动为其添加getter和setter使用@computed来注解一个计算属性使用@action来注解一个修改store的方法,类似于Vuex里的mutations示例代码: import 'package:mobx/mobx.dart';part 'counter.g.dart';class Counter = CounterBase with _$Counter;abstract class CounterBase with Store { @observable int value = 0; @computed int get allowCount { return value*2; } @action void increment() { value++; }}使用Mobx必须的一个步骤,就是前置编译步骤。我们编写Mobx的状态脚本,需要在前置编译环节,编译成dart可读的脚本,为此我们需要执行flutter pub run build_runner build生成.g.dart为后缀的文件(其实就是将注解转义为getter和setter)。UI更新方式 ...

June 18, 2020 · 1 min · jiezi

国内大厂都在使用哪些移动跨平台框架

自从移动应用开发兴起以来,不少公司和开发者就在不断的探索移动跨平台开发技术,以适应移动应用高速迭代的需求 。纵观当前的移动跨平台方案,总结一下无外乎三大类:一种是使用原生内置的浏览器加载HTML5的Hybrid技术,采用此方案的主要有Cordova、Ionic和微信小程序;另一种是使用JavaScript开发,然后使用原生组件进行渲染,采用此方案的主要有React Native、Weex和快应用;最后一种是使用自带的渲染引擎和自带的原生组件实现跨平台,采用这种方案的主要是Flutter。 抛开传统的Hybrid技术技术,目前比较流行的移动跨平台技术方案当属React Native、Weex和Flutter。不过,从开发效率、渲染性能、维护成本和社区生态上等不同的细节来看又各有优劣,对比如下。不过,综合对比下来说,Flutter应该是目前最好的,React Native次之,不过,正如我之前说的一样,对于移动跨平台技术,没有最好,只有适合自己的。 前不久,有网友对目前国内的大厂采用的移动跨平台技术进行了统计,给出了如下一组数据。 AppSwiftReact NativeFlutterWeexVersion1. 钉钉 ✔5.0.52. 腾讯会议 1.3.03. 剪映✔ 2.7.14. TestFlight✔ 2.6.05. 微视✔ 6.6.06. 快手极速版 2.1.37. 抖音 ✔ 9.9.08. 企业微信 3.0.139. 腾讯视频 8.0.010. 拼多多 5.3.011. 微信 7.0.1112. QQ ✔ 8.2.913. 快手 ✔ 7.1.514. 旅行世界✔ 1.2.015. 番茄小说 2.7.516. 支付宝 ✔ 10.1.8717. 手机淘宝✔ ✔9.5.018. 学习强国 2.9.219. 百度✔✔ 11.19.020. 韩剧TV-追剧大本营 4.6.821. 哔哩哔哩 5.54.122. 京东 ✔ 8.5.223. 小红书✔✔ 6.36.124. 爱奇艺 ✔ 11.2.525. 闲鱼 ✔✔6.6.5026. 优酷 ✔✔8.5.427. WPS Office 10.0.328. 网易云音乐 ✔ 7.0.2029. 腾讯课堂✔✔✔ 4.8.530. 淘宝直播 ✔1.6.131. 交管12123 2.4.432. QQ浏览器 ✔ 10.1.033. 西瓜视频 ✔✔ 4.3.034. 百度网盘✔ ✔ 10.0.9135. 美图秀秀✔ 8.7.7036. 喜马拉雅 ✔ 6.6.5437. 酷狗音乐 10.0.438. 好省✔ 2.2.039. 七猫小说✔ 3.040. QQ音乐 ✔ 9.8.541. 京东金融 ✔ 5.3.5042. Keep✔ 6.36.043. 微博 ✔10.3.044. BOSS直聘 7.20045. UC浏览器 ✔✔12.8.6.127446. 人人视频 4.3.647. 58同城 ✔ 9.6.148. 全民K歌 ✔ 6.19.849. 轻颜相机✔ 2.9.150. 网上国网 ✔2.0.251. 皖事通 1.6.1152. 安居客 ✔ 12.26.453. 淘宝特价版 ✔ 3.14.154. 今日头条 ✔✔ 7.6.155. 高德地图 10.28.056. 芒果TV✔ 6.5.657. 菜鸟裹裹 ✔ ✔5.9.058. 得物(毒)✔✔ 4.33.559. 贝壳找房 2.27.160. 美团 ✔ 10.7.40161. 第一弹 2.36.562. PP体育 5.20.263. 知乎✔ 6.31.264. 手机天猫 ✔9.5.165. Zoom 4.6.766. QQ邮箱 5.7.467. WiFi万能钥匙 5.8.368. 中国建设银行 4.3.2.00169. 作业帮 12.7.470. 农行掌上银行 4.2.071. 团油✔ 5.2.272. 美团外卖 ✔ 7.31.173. 虎牙直播 ✔✔ 7.10.074. 中国工商银行✔✔ 5.1.0.1.175. 搜狗输入法 10.5.076. 饿了么 ✔8.30.277. 扫描全能王 5.17.078. 流利说·英语✔ 7.14.079. 百度贴吧 ✔ 11.2.180. 智联招聘✔ ✔7.9.4781. 搜狐视频 7.9.282. 中国移动 6.083. 人民智云 1.4.284. 腾讯新闻 ✔ 6.0.4185. 苏宁易购 8.5.086. 酷狗铃声 2.4.087. 一甜相机 2.1.988. 下厨房 7.3.189. 一直播 3.2.490. TT语音✔ 5.0.991. 阿里巴巴 ✔8.20.592. 我的常州 1.3.593. 刷宝短视频✔ 2.094. 比心陪练 4.8.097. 中国银行手机银行✔ 6.5.0114. 招商银行 8.1.5151. 百度地图 10.23.0170. 星巴克中国✔ 7.10.1206. 滴滴出行✔ ✔5.4.4353. 网易新闻 65.1通过统计,得出如下的统计结果。 ...

June 18, 2020 · 3 min · jiezi

实战-Flutter-上的内存泄漏监控

一、前言Flutter 所使用的 Dart 语言具有垃圾回收机制,有垃圾回收就避免不了会内存泄漏。在 Android 平台上有个内存泄漏检测工具 LeakCanary,它可以方便地在 debug 环境下检测当前页面是否泄漏。本文将会带你实现一个 Flutter 可用的 LeakCanary,并讲述我是怎么用该工具检测出了 1.9.1 Framework 上的两个泄漏。 二、Dart 中的弱引用在具有垃圾回收的语言中,弱引用是检测对象是否泄漏的一个好方式。我们只需弱引用观测对象,等待下次 Full GC,如果 GC 之后对象为 null,说明被回收了,如果不为 null 就可能是泄漏了。 Dart 语言中也有着弱引用,它叫 Expando<T> ,看下它的 API: <!-- skip --> class Expando<T> { external T operator [](Object object ""); external void operator []=(Object object, T value);}你可能会好奇上述代码弱引用体现在哪里呢?其实是在 expando[key]=value 这个赋值语句上。Expando 会以弱引用的方式持有 key,这里就是弱引用的地方。 那么问题来了,这个 Expando 弱引用持有的是 key,但是本身又没有提供 getKey() 这样的 API,我们就无从下手去得知 key 这个对象是否被回收了。 为了解决这个问题,我们来看下 Expando 的具体实现,具体的代码在 expando_path.dart: <!-- skip --> ...

June 17, 2020 · 4 min · jiezi

Flutter实战图片组件及四大案例

老孟导读:大家好,这是【Flutter实战】系列文章的第三篇,这一篇讲解图片组件,Image有很多高级用法,希望对您有所帮助。图片组件是Flutter基础组件之一,和文本组件一样必不可少。图片组件包含Image和Icon两个组件,本质上Icon不属于图片组件,但其外形效果上类似于图片。 在项目中建议优先使用Icon组件,Icon本质上是一种字体,只不过显示的不是文字,而是图标,而Image组件先通过图片解码器将图片解码,所以Icon有如下优点: 通常情况下,图标比图片体积更小,显著的减少App包体积。图标不会出现失真或者模糊的现象,例如将20x20的图片,渲染在200x200的屏幕上,图片会失真或模糊,而图标是矢量图,不会失真,就像字体一样。多个图标可以存放在一个文件中,方便管理。全平台通用。ImageImage组件用于显示图片,图片的来源可以是网络、项目中图片或者设备上的图片。 加载网络图片: Image.network( 'http://pic1.win4000.com/pic/c/cf/cdc983699c.jpg',)加载项目中图片: 首先将图片拷贝到项目中,通常情况下,拷贝到assets/images/目录下,assets/images/目录为手动创建,新建的项目默认是没有此目录的。 设置pubspec.yaml配置文件: assets: - assets/images/或者指定具体图片的名称: assets: - assets/images/aa.jpg通常情况下,使用第一种方式,因为图片会有很多张,增加一张就这里配置一个太麻烦。 注意:assets前面的空格问题,极容易引发编译异常,正确格式如下: 加载图片: Image.asset('assets/images/aa.jpg')加载设备上的图片: 要加载设备(手机)上的图片首先需要获取设备图片的路径,由于不同平台的路径不同,因此路径的获取必须依靠原生支持,如果了解原生(Android和iOS)开发,可以直接使用MethodChannel获取路径,如果不懂原生(Android和iOS)开发,可以使用第三方插件获取路径,这里推荐官方的path_provider。 加载设备上的图片: Image.file(File('path')) 设置图片的大小: Image.asset('assets/images/aa.jpg',width: 100,height: 200,), 当Image的大小和图片大小不匹配时,需要设置填充模式fit,设置组件大小为150x150, Container( color: Colors.red.withOpacity(.3), child: Image.asset('assets/images/aa.jpg',width: 150,height: 150),) 看到,图片左右两边有空白区域(浅红色填充的区域),如果想要图片充满整个区域,设置如下: Container( color: Colors.red.withOpacity(.3), child: Image.asset('assets/images/aa.jpg',width: 150,height: 150,fit: BoxFit.fill,),) 虽然图片充满整个区域,但图片变形了,使图片等比拉伸,直到两边都充满区域: Container( color: Colors.red.withOpacity(.3), child: Image.asset('assets/images/aa.jpg',width: 150,height: 150,fit: BoxFit.cover,),) 此时,图片未变形且两边都充满区域,不过图片被裁减了一部分。 fit参数就是设置填充方式,其值介绍如下: fill:完全填充,宽高比可能会变。contain:等比拉伸,直到一边填充满。cover:等比拉伸,直到2边都填充满,此时一边可能超出范围。fitWidth:等比拉伸,宽填充满。fitHeight:等比拉伸,高填充满。none:当组件比图片小时,不拉伸,超出范围截取。scaleDown:当组件比图片小时,图片等比缩小,效果和contain一样。 BoxFit.none的裁减和alignment相关,默认居中, Image.asset( 'assets/images/aa.jpg', width: 150, height: 150, fit: BoxFit.none, alignment: Alignment.centerRight,), ...

June 16, 2020 · 2 min · jiezi

Flutter-实战指导使用ScopedModel管理状态

ScopedModel已经过度到了Provider的模式了。不用深入本文,就可以看到ScopedMode里的VM这一层都是通过调用notifyListeners方法来通知界面更新的,ScopedModel和ScopedModelDescendant也和Provider模式下的Consumer相差无几,底层也许有区别不过本质都是一个组件。而且也是用在需要更新的组件子树上一层来保证更新范围最小。在VM的组织上基本也是一样,用VM层来调用各种服务。所以,如果你已经了解Provider模式,那么本片可以不用看。不了解Provider也可以直接跳过本文看Provider模式。本文希望在尽量接近实战的条件下能清晰的讲解如何使用ScopedModel架构。视频教程在这里。 起因我(作者)在帮一个客户使用Flutter重制一个App。设计差强人意,性能更是差的离谱。但是我(作者)接手这个项目的时候还只用了Flutter三个星期。调研了ScopedMode和Redux之后就准备用ScopedModel了,BLoC完全不在考虑范围内。 我发现ScopedModel非常容易使用,而且从我开发这个app里我也有很多的收获。 实现风格ScopedModel不止有一种实现方式。根据功能组织Model,或者根据页面来组织Model。两种方法里model都需要和服务(service)交互,服务则处理所有的逻辑并且根据返回的数据处理状态(state)。我们来快速的过一下这两种方式。 一个AppModel和FeatureModel mixin 在这个情况下你有一个AppModel,它会从根组件(root widget)一直传递到需要的子组件上。AppModel可以通过mixin的方式来扩展它所支持的功能比如: /// Feature model for authenticationclass AuthModel extends Model { // ...}/// App modelclass AppModel extends Model with AuthModel {}如果你还是不清楚是怎么回事的话,可以看这个例子。 每个页面或者组件一个Model 这样一个ScopedModel就直接和一个页面或者组件关联了。但是也会产生很多的固定模式的代码,毕竟你要为每个页面写一个Model。 在(作者)的生产app上,使用了单一AppModel和多个功能mixin的方式。随着App规模的变大,经常会有一个model处理多个页面(组件)的状态的情况,这样就有点郁闷了。于是就迁移到了另外一种做法上。每个页面/组件一个Model,加上GetIt做为IoC容器,这样就简单了很多。本文的剩余部分也会继续讲述这个模式。 如果要动手实践的话可以从这个repo里代代码开始。用你喜欢的IDE打开start目录。 实现概述这么做是为了更加容易开始,也容易找到切入点。每个视图会有一个根Model继承自ScopedModel。ScopedModel对象将会从locator里获得。叫做locator是因为它就是用来定位服务和Model的。每个页面/组件的model都会代理专门的服务的方法,比如网络请求或者数据库操作等,并根据返回的结果更新组件的状态。 首先,我们来安装GetIt和ScopedModel。 实现配置和安装ScopedModel和依赖注入在我们的包清单pubspec里添加scoped_model和get_it依赖: ...dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 # scoped model scoped_model: ^1.0.1 # dependency injection get_it: ^1.0.3...在lib目录下新建一个service_locator.dart文件。添加如下代码: ...

June 13, 2020 · 4 min · jiezi

如何逆向Flutter应用

Flutter 简介Flutter 作为⾕歌推出的⼀个跨平台移动应⽤开发框架,可以帮助开发者快速在移动 iOS 、Android 上构建⾼质量的原⽣⽤户界⾯,同时还支持开发Web和桌面应用。自2018 年 12 ⽉ Flutter 1.0 版本发布以来,Flutter受到越累越多的开发者的追捧。截⾄⽬前, Flutter 在 GitHub 上已经获得了 93.1K 的 Star 和 12.6K的 Fork ,发展速度相当惊⼈。 目前,使用Flutter进行工程化开发的有阿⾥、腾讯、字节跳动、美团等知名⼤⼚,当然,除此之外,还有一些个人个中小企业,详细可以查看Flutter开发现状。众所周知,不同意React Native和Weex等跨平台技术方案,Flutter是一款自带渲染引擎的跨平台开发框架,它有自己的渲染管线和 Widget 库,因而开发出的应用体验更好。如下图所示,是Flutter官方给出的架构示意图。可以看到,Flutter框架主要分为Framework、Engine和 Embedder三层。其中,Framework使用Dart语言实现,包括UI、文本、图片、按钮等Widgets,渲染,动画,手势等,与开发者直接交互的就是这一层。Engine使用C++实现,主要包括Skia、Dart 和 Text。 Skia是开源的二维图形库,提供了适用于多种软硬件平台的通用API。其已作为Google Chrome,Chrome OS,Android, Mozilla Firefox, Firefox OS等其他众多产品的图形引擎,支持平台还包括Windows, macOS, iOS,Android,Ubuntu等。Dart 部分主要包括:Dart Runtime,Garbage Collection(GC),如果是Debug模式的话,还包括JIT(Just In Time)支持。Release和Profile模式下,是AOT(Ahead Of Time)编译成了原生的arm代码,并不存在JIT部分。Text 即文本渲染,其渲染层次如下,衍生自 Minikin的libtxt库(用于字体选择,分隔行);HartBuzz用于字形选择和成型;Skia作为渲染/GPU后端,在Android和Fuchsia上使用FreeType渲染,在iOS上使用CoreGraphics来渲染字体。Embedder则是一个嵌入层,该层的主要作用是把Flutter嵌入到各个平台上去,它的主要工作包括渲染Surface设置, 线程设置,以及插件等。平台(如iOS)只是提供一个画布,剩余的所有渲染相关的逻辑都在Flutter内部,这就使得它具有了很好的跨端一致性。 由于平时进行应用开发时和我们打交道最多的就是Framework层,并且该层主要使用 Dart 语言进行编写,也是应用程序所有业务逻辑所在的位置,因此,逆向Flutter应用主要的工作就在这一层。 逆向基础由于Flutter 将 Dart 编译为本机汇编代码使用的格式尚未公开,因此尽管没有混淆或加密,但 Flutter 应用程序目前仍然很难逆向,因为需要深入了解 Dart 内部知识才能了解到皮毛。而比较其他应用而言,React Native 使用的是容易检查和修改的 Javascript,而 Android 使用的 Java 有详细的字节码说明,并且有许多免费的反编译器,因此逆向要容易许多。 ...

June 10, 2020 · 6 min · jiezi

Flutter-BLoC模式入门

原文地址在这里, 作者是Brian Kayfitz。 这里提一点关于IDE的问题,很多人是移动转过来的,所以用Android Studio的人很多。其实Flutter也可以用VS Code来开发。笔者,两个都用过,他们各有好处。Android Studio在项目初期,目录、文件处理多的时候方便。重构的时候关于文件的修改,都会在其他文件引用里一起修改,删除也会有提示。在VS Code里这些没有,改文件名要手动去把import也一起改了。但是,VS Code调试方便很多。但是,在真机调试的时候还是要记得先Select Device。 正文设计app的架构经常会引起争论。每个人都有自己喜欢的一套炫酷的架构和一大堆名词。 iOS和Android开发者都对MVC非常了解,并且在开发的时候把这个模式作为默认的架构。Model和View是分开的,Controller来作为他们沟通的桥梁。 然而,Flutter带来的一套响应式设计并不能很好的兼容MVC。一个脱胎于这个经典模式的新的架构就出现在了Flutter社区--BLoC。 BLoC是Business Logic Components的缩写。BLoC的哲学就是app里的所有东西都应该被认为是事件流:一部分组件订阅事件,另一部分组件则响应事件。BLoC居中管理这些会话。Dart甚至把流(Stream)内置到了语言本身里。 这个模式最好的地方就是你不需要引入任何的插件,也不需要学习其他的语法。所有需要的内容Flutter都有提供。 在本文里,我们要新建一个查找餐厅的app。API是有Zomato提供。最后你会学到以下内容: 在BLoC模式里包装API调用查找并异步显示结果维护一个可以从多个页面访问到的最爱餐厅列表开始在这里下载开始项目代码,使用你最喜欢的IDE打开。记得开始的时候运行flutter pub get,在IDE里也好,在命令行里也可以。在所有依赖都下载完成后就可以开始编码了。 在开始项目里包含了基本的model文件和网络请求文件。看起来是这样的: 获取API的Key在开始开发应用之前,首先要获得一个我们要用的API的key。在Zomato的开发者站点https://developers.zomato.com/api,注册并生成一个key。 在DataLayer目录下,打开zomato_client.dart文件。修改这个常量值: class ZomatoClient { final _apiKey = "Your api key here";}实际的开发中把key放进源码或者夹杂到版本控制工具里可不是什么明智之举。这里只是为了方便,可不要用在实际的开发里。运行起来,你会看到这样的效果: 一片黑,现在开始添加代码: 我们来烤一个多层蛋糕写app的时候,不管你用的是Flutter或者其他的框架,把类分层都是很关键的。这更像是一个非正式的约定,不是一定要在代码里有怎么样的体现。 每层,或者一组类,都负责一个总体的职责。在初始项目里有一个目录DataLayer。这个数据层专门用来负责app的model和与后台通信。它对UI一无所知。 每个app都不尽相同,但是总体来说你都会构建一个这样的东西: 这个架构约定并没有和MVC太过不同。UI/Flutter层只能和BLoC层通信,BLoC层处理逻辑并给数据层和UI发送事件。这样的结构可以保证app规模变大的时候可以平滑的扩展。 深入BLoCBLoC基本就是基于Dart的流(Stream)的。 流,和Future一样,也是在dart:async包里。一个流就像一个future,不同的是流不只是异步的返回一个值,流可以随着时间的推移返回很多的值。如果一个future最终是一个值的话,那么一个流就是会随着时间可以返回一个系列的值。 dart:async包提供了一个StreamController类。流控制器管理的两个对象流和槽(sink)。sink和流相对应,流提供提供数据,sink接受输入值。 总结一下,BLoC用来处理逻辑,sink接受输入,流输出。 定位界面在查找餐馆之前,你要告诉Zomato你要在哪里吃饭。在这一节,你要新建一个简单的界面,有一个搜索栏和一个列表显示搜索的结果。 在输入代码之前不要忘记打开DartFmt。这才是编写Flutter app的组好编码方式。在lib/UI目录,席间一个location_screen.dart文件。添加一个StatelessWidget,并命名为LocationScreen。 import 'package:flutter/material.dart';class LocationScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Where do you want to eat?')), body: Column( children: <Widget>[ Padding( padding: const EdgeInsets.all(10.0), child: TextField( decoration: InputDecoration( border: OutlineInputBorder(), hintText: 'Enter a location'), onChanged: (query) { }, ), ), Expanded( child: _buildResults(), ) ], ), ); } Widget _buildResults() { return Center(child: Text('Enter a location')); } }定位界面包含了一个TextField,用户可以在这里输入位置。 ...

June 8, 2020 · 6 min · jiezi

Flutter开发之动画

动画作为产品的重要组成部分,是提升用户体验的重要方式,一个恰当的动画不仅能够缓解用户因为等待而带来的情绪焦躁,还会增加应用的整体用户体验。因此,在应用中增加动画的相关功能,可以增强用户的粘性。 动画的原理不管是Android平台还是iOS平台,我们在使用应用时都能看到一些炫酷的动画效果。作为移动应用的重要组成部分,动画是提高用户体验的重要手段,一个恰当的动画,不仅能够缓解用户因为等待而带来的情绪问题,还会提升用户使用的体验。事实上,不管是什么视图框架,动画的实现原理都是相同的,即在一段有限的时间内,多次快速地改变视图外观来实现一个连续播放的效果。视图的一次改变即称为一个动画帧,对应一次屏幕刷新,而决定动画流畅度的一个重要指标就是帧率FPS(Frame Per Second缩写),即每秒的动画帧数。很明显,帧率越高则动画就会越流畅。目前,大多数设备的屏幕刷新频率可以到达60Hz,而对于人眼来说,动画帧率超过16FPS就认为是流畅的,超过32FPS基本就感受不到任何卡顿。由于动画的每一帧都需要改变视图的输出,所以在一个时间段内连续的改变视图输出是比较耗费资源的,对设备的软硬件系统要求也比较高。作为衡量一个视图框架优劣的标准,Flutter框架在理想情况下是可以实现60FPS的,这和原生应用的帧率标准是基本是持平的。同时,为了方便开发者创建并使用动画,不同的视图框架对动画都进行了高度的抽象和封装,比如在Android开发中,可以使用XML来描述一个动画然后再设置给一个视图对象。同样,Flutter也对动画进行了高度的抽象,并且提供了Animation、Curve、Controller、Tween等四个动画对象。Animation是Flutter动画的核心抽象类,包含动画的当前值和状态两个属性。AnimationController是Animation的控制器,动画的开始、结束、停止、反向均由它控制,可以通过Listener和StatusListener来管理动画状态的改变。 动画API在Flutter中,学习动画相关的开发,其实就是围绕Animation、Curve、Controller、Tween等四个动画对象来展开的。 Animation在Flutter中,Animation是实现动画的核心类,Animation的主要作用就是保存动画的插值和状态,它本身与视图渲染没有任何关系。Animation对象则是一个可以在一段时间内依次生成一个区间值的类,其输出值可以是线性的、曲线的,可以是一个步进函数或者任何其他曲线函数等,由Curve来决定。Animation的核心源码如下: abstract class Animation<T> extends Listenable implements ValueListenable<T> { const Animation(); // 添加动画监听器 @override void addListener(VoidCallback listener); // 移除动画监听器 @override void removeListener(VoidCallback listener); // 添加动画状态监听器 void addStatusListener(AnimationStatusListener listener); // 移除动画状态监听器 void removeStatusListener(AnimationStatusListener listener); // 获取动画当前状态 AnimationStatus get status; // 获取动画当前的值 @override T get value;Animation是一个抽象类,Widget可以直接将这些动画合并到自己的build方法中来读取它们的当前值或者监听它们的状态变化。Animation提供了addListener和addStatusListener两个方法来监听动画帧的变化。 addListener addListener方法用于给Animation对象添加帧监听器,每一帧都会被调用,当帧监听器监听到状态发生改变后会调用setState()来触发视图的重建。这意味着: 每当动画的状态值发生变化时,动画都会通知所有通过 addListener 添加的监听器。一个正在监听动画的state对象会调用自身的setState方法,将自身传入这些监听器的回调函数来通知 widget 系统需要根据新状态值进行重新构建。addStatusListeneraddStatusListener方法用于给Animation对象添加动画状态改变监听器,动画开始、结束、正向或反向时会调用状态改变的监听器。这意味着: 当动画的状态发生变化时,会通知所有通过 addStatusListener 添加的监听器。动画会从 dismissed 状态开始,表示它处于变化区间的开始点。举例来说,从 0.0 到 1.0 的动画在 dismissed 状态时的值应该是 0.0。动画进行的下一状态可能是 forward(比如从 0.0 到 1.0)或者 reverse(比如从 1.0 到 0.0)。最终,如果动画到达其区间的结束点(比如 1.0),则动画会变成 completed 状态AnimationControllerAnimationController,即动画控制器,Animation是一个抽象类,并不能用来直接创建对象并实现动画,它的主要用于控制动画的开始、结束、停止、反向等操作。AnimationController是Animation的一个子类,默认情况下,AnimationController会在给定的时间段内以线性的方式生成从0.0到1.0的数字。它的源码如下: ...

June 7, 2020 · 4 min · jiezi

mac安装flutter

mac安装flutter一、下载flutter1、第一种方式git repo方式执行下列命令下载最新的flutter代码(系统请先安装Git) git clone -b beta https://github.com/flutter/flutter.git2、第二种方式官方网站flutter官网下载其最新可用的安装包,转到下载页。 二、安装flutter,环境配置,依赖项检查(1)目前接下来我的是使用官方网下载的zip压缩包。 (2)解压 (3)添加flutter相关工具到path中: export PATH=`pwd`/flutter/bin:$PATH这个命令只在当前命令行中设置PATH环境变量,要想永久将Flutter添加到PATH中请参考下面更新环境变量部分。 使用命令查看是否安装成功 ./bin/flutter --v检查flutter是否安装成功 (4)个人觉得还是使用永久的将flutter添加到path中 在用户文件夹下找到.bash_profile文件,如果没有就创建一个; export PUB_HOSTED_URL=https://pub.flutter-io.cn export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn export PATH=/Users/chengxinsong/Desktop/Tool/flutter/bin:$PATH添加保存后,执行下列命令刷新终端: source $HOME/.bash_profile运行下列命令检查flutter是否已经安装成功: flutter -v检查flutter是否安装成功 出现上述说明,安装成功。 (6)检查flutter的依赖项 flutter doctorflutter会提示你那些东西是必须要的,需要执行什么命令进行安装,按照提示安装即可;检查flutter的依赖性 三、第一个Flutter App打开VsCode VsCode需要安装两个扩展:Dart和Flutter。 按F1(有touchbar的机子按住fn可见F1)呼出命令输入框; 输入字符Flutter,在命令候选列表中选择Flutter: New Project,新建一个Flutter项目,随后让你填写项目名称和选择项目存放路径; 设置好flutter的安装路径的根目录。 项目创建好后,在VSCode右下角选择调试环境目标: 怎么启动?vscode已经提示f5启动项目。启动有点慢,等着就好了。 点击+号 四、欢迎关注show me code:https://github.com/saucxs/flu... 后续会出更多知识体系构建,技术分享,项目实战,实验室等,欢迎关注本公众号:[松宝写代码] 微信公众号:[松宝写代码]songEagle开发知识体系构建,技术分享,项目实战,实验室,带你一起学习新技术,总结学习过程,让你进阶到高级资深工程师,学习项目管理,思考职业发展,生活感悟,充实中成长起来。问题或建议,请公众号留言。微信群:【写代码】研发进阶群一个成长交流的产研群,帮忙拉产研的同学们进群,聚聚人气??。每一个开发同学都应该形成自己的知识体系,做到提纲挈领??? 五、各种福利关注微信公众号:[松宝写代码],有各种福利。 「字节跳动」内推福利: 1、社招内推 2、实习生内推 3、校招内推官网地址,投递时候填写内推码:8J5ZSB8

June 6, 2020 · 1 min · jiezi

Flutter开发之动态权限

众所周知,Android在6.0版本后将权限修改成了动态权限,而iOS则一直使用的是动态权限,所以在Flutter应用开发中如果涉及到一些危险权限,就需要进行动态申请,动态申请权限可以使用Flutter的permission_handler。 基本使用1,配置权限首先,打开Android工程下的AndroidManifest.xml文件,具体路径如下:在androidappsrcmainAndroidManifest.xml中配置,然后添加如下所示的权限。 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.kill_attendance"> <!-- 申请Android权限--> <!--网络访问--> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- Permissions options for the `contacts` group --> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <!-- Permissions options for the `storage` group --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Permissions options for the `camera` group --> <uses-permission android:name="android.permission.CAMERA" /> <!-- Permissions options for the `location` group --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- Permissions options for the `microphone` or `speech` group --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- app名称,图标 --> <application android:name="io.flutter.app.FlutterApplication" android:label="应用名称" android:icon="@mipmap/icon"> <activity android:name=".MainActivity" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"> <!-- This keeps the window background of the activity showing until Flutter renders its first frame. It can be removed if there is no splash screen (such as the default splash screen defined in @style/LaunchTheme). --> <meta-data android:name="io.flutter.app.android.SplashScreenUntilFirstFrame" android:value="true" /> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application></manifest>动态权限申请目前,这个插件已经升级了好几版,而不同版本处理方法也不一样,特别是最新的5.0.0版本和之前的版本,用法差别比较大。 ...

June 6, 2020 · 3 min · jiezi

Flutter-深入布局规则

本问现在是官方文档的一部分了当Fluter初学者问你为什么组件里的width:100不是100像素的时候,默认的答案就是告诉他们把组件放进一个Center里,对吧? 不要这么干。 如果你这么干了,他们会一次一次的问你为什么FittedBox有问题,为什么Column会overflow,又或者IntrinsicWidth是做什么的。 所以,一开始就告诉他们Flutter的布局和html有很大的不同,他们很可能就是html的高手,然后让他们记住以下的规则: ? 约束(Constraint)向下,大小(Size)向上,位置父决定不理解这个规则,Flutter的布局是没法弄清楚的。所以,我(作者)觉得最好今早的学会它。 细节: 一个组件都是从它的父组件获得约束(constraint)。一个约束就是四个double值:一个最小、最大宽度和一个最小、最大高度。然后,这个组件遍历它的子组件。一个个的通知它的子组件他们的约束(每个子组件都可能不一样),然后询问他们想要的size。然后,这个组件沿着横向的x轴和纵向的y轴排列它的子组件的位置。最后,每个组件告诉它的父组件它自己在约束下的size。比如一个Column组件,已经设定了padding值,现在要给它的两个子组件设定布局: 组件 -- 询问父组件约束是啥。父组件 -- 你只能是90到300宽,30到85高。组件 -- 嗯~~ 我还要5个单位的padding,那么我的子组件只能有最大290的宽和75的高。组件 -- 嗨,第一个子组件你必须是0 ~ 290宽,0 ~ 75高。第一个子组件 -- 我要290宽,20高。组件 -- 嗯~~ , 既然我要把第二个子组件放在第一个的下面,这样就剩下55的高度给第二个子组件了。组件 -- 嗨,第二个子组件你必须是0 ~ 290宽,0 ~ 55高。第二个子组件 -- 好的,我要140宽和30高。组件 -- 很好,我会把第一个子组件放在x轴:5,y轴:5,第二个子组件x轴:80,y轴:25的位置。组件 -- 嗨,父组件。我的size是300宽,60高。限制(Limitation)Flutter布局引擎在上面规则的基础上还有一些其他的限制: 一个组件只可以在父组件传过来的约束的范围内确定它的大小(size)。也就是说,一般一个组件不能想多大就多大。一个组件不知道,也不能决定它在屏幕上的位置。组件的位置是由它的父组件决定的。父组件的大小和位置也是由它的父组件决定的,只有在树的概念下才能决定一个组件的大小和位置。示例下面是一个互动示例。 原文提到了CodePen,也可以在以下两种方法里选一种。使用DartPad.代码的github repo示例 1 Container(color: Colors.red);屏幕是Container的父组件,它会把红色的Container严丝合缝的约束在整个的屏幕内部。 所以,Container填满了整个屏幕,到处都是红色。 示例 2 Container(color: Colors.red, width: 100, height: 100)Container想要宽100,高100,但是不行。屏幕会强制它填满屏幕。 所以Container填满了屏幕。 示例 3 屏幕强制Center填满整个屏幕,所以Center显示在全屏。 Center告诉Container可以拥有想要的大小,但是不能比屏幕还大。所以,Container的大小就是100x100。 示例 4 Align( alignment: Alignment.bottomRight, child: Container(width: 100, height: 100, color: Colors.red))这和前一个例子并不一样,这里用的是Align而不是Center。 ...

June 4, 2020 · 2 min · jiezi

Dart-学习笔记数据类型

Dart 数据类型数字字符串布尔列表listmap数字Dart有两种数字类型: 整数 - 整数值表示非小数值,即没有小数点的数值。 例如,值10是整数。整数文字使用 int 关键字表示。浮点型 - Dart也支持小数数值,即带小数点的值。 Dart中的Double数据类型表示64位(双精度)浮点数。例如,值10.10。关键字 double 用于表示浮点文字。字符串Dart字符串是一系列UTF-16代码单元。 Runs 用于表示UTF-32代码单元序列。关键字 String 用于表示字符串文字。字符串值嵌入单引号或双引号中。 布尔布尔数据类型表示布尔值true和false。Dart使用 bool 关键字表示布尔值。 列表list一个 列表 是对象的有序组。Dart中的List数据类型与其他编程语言中的数组概念同义。 映射map映射map数据类型表示一组值作为键-值对。dart:core 库分别使创建和这些集合的操作通过预定义列表和map类。 动态类型Dart是一种可选类型语言。如果未明确指定变量的类型,则变量的类型是 动态的 。dynamic 关键字也可以用来作为一种类型的注释明确。 声明变量的标准形式必须在使用变量之前声明变量。Dart使用var关键字来实现相同的目标,通过在变量名前加上数据类型来支持类型检查 。 var name = "xiaoma";dart中的所有变量都存储对该值的引用,而不是包含该值。名为name的变量包含对String对象的引用,其值为 "xiaoma"。 void main (){ int age; print(age);}//null所有未初始化的变量的初始值为null。这是因为Dart将所有值都视为对象。以下示例说明了相同的情况 dynamic 关键字声明没有静态类型的变量被隐式声明为动态。也可以使用dynamic关键字代替var关键字声明变量。 void main(){ dynamic x = "xiaoma"; print(x);}//xiaomafinal和const使用final和const关键字来声明常量。Dart阻止修改使用final或const关键字声明变量的值。这些关键字可以与变量的数据类型一起使用,也可以与 var 关键字一起使用。 const关键字用来表示一个编译时常数。使用const关键字声明的变量是隐式final的。 void main(){ //final声明常量 final name = "xiaoma"; print(name); //const声明常量 const pi = 3.14; const area = pi*12*12; print(area);}/*xiaoma452.15999999999997*/注:只有 const 变量可用于计算编译时常量。编译时常量是常量,其值将在编译时确定。 ...

June 3, 2020 · 1 min · jiezi

Dart-学习笔记面向对象基础

第一个 Dart 程序main () { print("Hello Dart!");}启动检查模式Dart以两种模式运行:Dart 1.x有生产模式和检查模式两种模式,Dart 2.x中移除了检查模式。 生产模式(默认)检查模式注:建议在开发/测试模式中使用检查模式运行Dart VM,因为它会添加警告和错误以帮助开发和调试过程;选中的模式会强制执行各种检查,例如类型检查等。 Dart 标识符dart标识符可以包括字符和数字,但不能以数字开头。 除下划线(_)或美元符号($)外,标识符不能包含特殊符号。标识符不能是关键字。它们必须是唯一的。标识符区分大小写。标识符不能包含空格。Dart 注释单行注释//多行注释/* */Dart 面向对象编程(OOP)Dart 是一种面向对象的编程语言。 对象 - 对象是任何实体的实例。 根据Grady Brooch,每个对象必须具有三个功能:状态 - 由对象的属性描述。行为 - 描述对象的行为方式。标识 - 将对象与一组类似此类对象区分开的唯一值。类 - OOP方面的类是创建对象的蓝图。 类封装了对象的数据。方法 - 方法促进对象之间的通信。class TestClass{ void disp(){ print("Hello Dart!"); }}void main(){ TestClass c = new TestClass(); c.disp();}/*Hello Dart!*/代码说明:定义了一个类TestClass,这个类拥有一个方法disp(),方法可以实现在终端打印字符串Hello Dart!,使用new 关键字创建类的对象,该对象调用方法disp()。

June 3, 2020 · 1 min · jiezi

Dart-学习笔记前言

前言由于毕业设计抱着作死(<s>美名其曰为开荒</s>)的心态选了个Flutter相关的题目,遂谷歌,了解到Flutter是基于Dart语言开发的一个移动UI框架,需要一定的Dart语言基础,所以打算用一周的时间把Dart的基础语法过一遍,先来介绍一下什么是Dart吧! Dart是一种“结构化”的编程语言,它的创始人是Lars Bak,由谷歌于2011年在丹麦举行的发布会上宣布推出,据说当时是以取代JavaScript为目标,然而近十年过去了,反观其昔日的对手JavaScript已经衍生出React和Vue等数款热门前端框架,而Dart一直是不温不火,如果不是专门从事移动端的开发者,想必在国内也很少听说过Dart,不过这种情况直到Flutter的诞生才得以改变,有关于Flutter的部分会在之后的深入学习再介绍。令人感到欣喜的是,国内对Dart语言社区的生态也越来越重视起来,这里介绍一些我经常逛的社区: Dart.cnDart中文网Flutter.cn:结合fullter学习dart的一些知识Dart开发者社区:重庆老朋友办的社区,支持一下!Dart中文社区:略微沉寂,更新缓慢掘金Dart专栏Dart 版本特性Dart 1.02013年11月14日,谷歌发布Dart 1.0版本,其标题为《Dart 1.0: A stable SDK for structured web apps》。一个专门为Dart语言设计的虚拟机;一个Dart2JS编译工具用于将Dart编译为JavaScript目标代码;一个基于Eclipse为Dart定制的Dartium IDE集成开发环境;其中Dartium不仅仅包含了Dart一整套工具链, 而且包含了一个内置Dart虚拟机的Chrome浏览器!同时,当时热门的前端开发框架AngularJS移植到了Dart环境。 Dart 2.02018年8月8日,谷歌发布Dart2.0版本,其标题为《Announcing Dart 2 Stable and the Dart Web Platform》。Dart 2.0针对服务端开发/Web开发/手机开发三大领域做了深度定制细分的工作。首先Dart语言的标准库为服务器端开发提供了dart:io等诸多支持。在Web方向,Dart继续和Angular框架进行深度整合。最大的亮点是针对手机设备的Flutter跨平台的开发框架,它为Dart语言带来了Ahead-of-time编译技术,可以将Dart语言开发的程序直接编译为本地机器码运行。同时,Dart 2.0语言针对客户端开发大大加强和精简了类型系统。 虽然Dart有着诸多优秀的特性,国内使用Dart语言开发的人并不多,直到Flutter框架的推出,并且作为Google开发Fuchsia OS的底层使用语言(<s>Fuchsia 一统天下!</s>>),Dart才再次回到开发人员的视线,并将可能成为未来最重要的全栈开发编程语言,从现在开始,一切都来得及!

June 3, 2020 · 1 min · jiezi

Flutter-动画鼻祖之CustomPaint

老孟导读:CustomPaint可以称之为动画鼻祖,它可以实现任何酷炫的动画和效果。CustomPaint本身没有动画属性,仅仅是绘制属性,一般情况下,CustomPaint会和动画控制配合使用,达到理想的效果。基本用法CustomPaint的用法非常简单,如下: CustomPaint( painter: MyCustomPainter(),)MyCustomPainter定义如下: class MyCustomPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) {} @override bool shouldRepaint(MyCustomPainter oldDelegate) { return this != oldDelegate; }}上面的MyCustomPainter为了看起来清晰,什么也没有做,通常情况下,在paint方法内绘制自定义的效果。shouldRepaint方法通常在当前实例和旧实例属性不一致时返回true。 paint通过canvas绘制,size为当前控件的大小,下面看看canvas的方法。 绘制点Paint _paint = Paint() ..color = Colors.red ..strokeWidth = 3; @override void paint(Canvas canvas, Size size) { var points = [ Offset(0, 0), Offset(size.width / 2, size.height / 2), Offset(size.width, size.height), ]; canvas.drawPoints(PointMode.points, points, _paint); } PointMode有3种模式: points:点lines:将2个点绘制为线段,如果点的个数为奇数,最后一个点将会被忽略polygon:将整个点绘制为一条线绘制线canvas.drawLine(Offset(0, 0),Offset(size.width, size.height), _paint); ...

June 2, 2020 · 1 min · jiezi

flutter笔记1

一.Text1.TextAlign// 对齐child:Text( '非常喜欢前端,并且愿意为此奋斗一生。我希望可以出1000集免费教程。', textAlign:TextAlign.left,)/**textAlign:TextAlign.left * center: 文本以居中形式对齐,这个也算比较常用的了。* left:左对齐,经常使用,让文本居左进行对齐,效果和start一样。* right :右对齐,使用频率也不算高。* start:以开始位置进行对齐,类似于左对齐。* end: 以为本结尾处进行对齐,不常用。有点类似右对齐*/2.maxLines设置最多显示的行数,比如我们现在只显示1行child:Text( '非常喜欢前端,并且愿意为此奋斗一生。我希望可以出1000集免费教程。', textAlign:TextAlign.left, maxLines: 1,)3.overflowoverflow属性是用来设置文本溢出时,如何处理child:Text( '非常喜欢前端,并且愿意为此奋斗一生。我希望可以出1000集免费教程。', textAlign:TextAlign.left, overflow: clip,)/** clip:直接切断,剩下的文字就没有了* ellipsis:在后边显示省略号,体验性较好* fade: 溢出的部分会进行一个渐变消失的效果***/4.stylestyle属性较多child:Text( '非常喜欢前端,并且愿意为此奋斗一生。我希望可以出1000集免费教程。', textAlign:TextAlign.left, overflow:TextOverflow.ellipsis, maxLines: 1, style: TextStyle( fontSize:25.0, color:Color.fromARGB(255, 255, 150, 150), decoration:TextDecoration.underline, decorationStyle:TextDecorationStyle.solid, ),)/* inherit: true, // 为false的时候不显示 color: Color.fromARGB(255, 150, 150, 150), // 颜色 fontSize :22.0, // 字号 fontWeight: FontWeight.w700, // 字重,加粗也用这个字段 FontWeight.w700 fontStyle: FontStyle.italic , // FontStyle.normal FontStyle.italic斜体 letterSpacing: 10.0, // 字符间距 就是单个字母或者汉字之间的间隔,可以是负数 wordSpacing: 15.0, // 字间距 句字之间的间距 textBaseline: TextBaseline.alphabetic, // 基线,两个值,字面意思是一个用来排字母的,一人用来排表意字的(类似中文) textBaseline: TextBaseline.ideographic height: 1.0, // 当用来Text控件上时,行高(会乘以fontSize,所以不以设置过大) decoration: TextDecoration.overline, // 添加上划线 decoration: TextDecoration.lineThrough, // 添加删除线 decoration: TextDecoration.underline, // 添加下划线 decorationColor, // 划线的颜色 decorationStyle: TextDecorationStyle.dotted, // 这个style可能控制画实线,虚线,两条线,点, 波浪线等 debugLabel, background: //文本背景色 String fontFamily, // 字体 String package,*/二.Container容器组件Container(容器控件)在Flutter是经常使用的控件,它就相当于我们HTML里的<div>标签1.padding属性padding的属性就是一个内边距child:Container( child:new Text('Container容器组件', style: TextStyle(fontSize: 40.0) ), alignment: Alignment.topLeft, width:500.0, height:400.0, color: Colors.lightBlue, padding:const EdgeInsets.all(10.0),)padding:const EdgeInsets.all(10.0),设置Container的内边距是10,左右上下全部为10padding:const EdgeInsets.fromLTRB(10.0,30.0,0.0,0.0)可以满足我们分别设置上下左右,LTRB分别代表左、上、右、下2.margin属性child:Container( child:new Text('Hello JSPang', style: TextStyle(fontSize: 40.0) ), alignment: Alignment.topLeft, width:500.0, height:400.0, color: Colors.lightBlue, padding:const EdgeInsets.fromLTRB(10.0,30.0,0.0,0.0), margin: const EdgeInsets.all(10.0),)3.decoration属性decoration是 container 的修饰器,主要的功能是设置背景和边框比如你需要给背景加入一个渐变,和边框 这时候需要使用BoxDecoration这个类注意:需要注意的是如果你设置了decoration,就不要再设置color属性了,因为这样会冲突child:Container( child:new Text('Hello JSPang',style: TextStyle(fontSize: 40.0),), alignment: Alignment.topLeft, width:500.0, height:400.0, padding:const EdgeInsets.fromLTRB(10.0,30.0,0.0,0.0), margin: const EdgeInsets.all(10.0), decoration:new BoxDecoration( gradient:const LinearGradient( colors:[Colors.lightBlue,Colors.greenAccent,Colors.purple] ), border:Border.all(width:2.0,color:Colors.red) ))三.Image图片组件的使用1.加入图片的几种方式1.Image.asset:加载资源图片,就是加载项目资源目录中的图片,加入图片后会增大打包的包体体积,用的是相对路径。2.Image.network:网络资源图片,意思就是你需要加入一段http://xxxx.xxx的这样的网络路...。3.Image.file:加载本地图片,就是加载本地文件中的图片,这个是一个绝对路径,跟包体无关。4.Image.memory: 加载Uint8List资源图片 ...

June 2, 2020 · 7 min · jiezi

Flutter-Provider-迄今为止最深最全最新的源码分析

回顾Flutter State Management状态管理全面分析上期我们对Flutter的状态管理有了全局的认知,也知道了如何分辨是非好坏,不知道也没关系哦,我们接下来还会更加详细的分析,通过阅读Provider源码,来看看框架到底如何组织的,是如何给我们提供便利的。 本期内容通过官方我们已经知道其实Provider就是对InheritedWidget的包装,只是让InheritedWidget用起来更加简单且高可复用。我们也知道它有一些缺点,如 容易造成不必要的刷新不支持跨页面(route)的状态,意思是跨树,如果不在一个树中,我们无法获取数据是不可变的,必须结合StatefulWidget、ChangeNotifier或者Steam使用我特别想弄明白,这些缺点在Provider的设计中是如何规避的,还有一个是Stream不会主动的close掉流的通道,不得不结合StatefulWidget使用,而Provider提供了dispose回调,你可以在该函数中主动关闭,好厉害,如何做到的呢?带着这些疑问,我们去寻找答案 如何使用我们先来使用它,然后在根据用例分析源码,找到我们想要的答案,先看一个简单的例子 step 1第一步定义一个ChangeNotifier,来负责数据的变化通知 class Counter with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); }}step 2第二步,用ChangeNotifierProvider来订阅Counter,不难猜出,ChangeNotifierProvider肯定是InheritedWidget的包装类,负责将Counter的状态共享给子Widget,我这里将ChangeNotifierProvider放到了Main函数中,并在整个Widget树的顶端,当然这里是个简单的例子,我这么写问题不大,但你要考虑,如果是特别局部的状态,请将ChangeNotifierProvider放到局部的地方而不是全局,希望你能明白我的用意 void main() { runApp( /// Providers are above [MyApp] instead of inside it, so that tests /// can use [MyApp] while mocking the providers MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => Counter()), ], child: MyApp(), ), );}step 3第三步,接收数据通过Consumer<Counter>,Consumer是个消费者,它负责消费ChangeNotifierProvider生产的数据 ...

May 31, 2020 · 8 min · jiezi

Flutter-State-Management状态管理全面分析

前言2019 Google I/O 大会,google就推出Provider,成为官方推荐的状态管理方式之一,Flutter 状态管理一直是个很热门的话题,而且状态管理的库也是超级多,这确实是我们每一个做Flutter开发难以避免的一道坎,既然这么重要,我们如何去理解它,如何使用它,如何做到更好呢?接下来让我告诉你答案 啰嗦几句该文章已经经历了一周的迭代,预计还要一周左右,要做一个全面的分析,当然要每个细节都要关注到,如果您觉得好,请不要吝啬您的大拇指,顺便点个赞哦,么么哒,如果有不对的地方提出来,一个地方一个红包奖励哦,爱你们。 主要内容 一张图告诉你,我要讲的主要内容。下面将围绕这八个方面来讲。七个理论,一个实践。 状态管理是什么为什么需要状态管理状态管理基本分类状态管理的底层逻辑状态管理的使用原则使用成熟状态管理库的弊端选择状态管理库的原则Provider 深入分析(学以致用)状态管理是什么我们知道最基本的程序是什么: 程序=算法+数据结构数据是程序的中心。数据结构和算法两个概念间的逻辑关系贯穿了整个程序世界,首先二者表现为不可分割的关系。其实Flutter不就是一个程序吗,那我们面临的最底层的问题还是算法和数据结构,所以我们推导出 Flutter=算法+数据结构那状态管理是什么?我也用公式来表达一下,如下: Flutter状态管理=算法+数据结构+UI绑定瞬间秒懂有没有?来看一个代码例子: class ThemeBloc { final _themeStreamController = StreamController<AppTheme>(); get changeTheTheme => _themeStreamController.sink.add; get darkThemeIsEnabled => _themeStreamController.stream; dispose() { _themeStreamController.close(); }}final bloc = ThemeBloc();class AppTheme { ThemeData themeData; AppTheme(this.themeData);}/// 绑定到UIStreamBuilder<AppTheme>( initialData: AppTheme.LIGHT_THEME, stream: bloc.darkThemeIsEnabled, builder: (context, AsyncSnapshot<AppTheme> snapshot) { return MaterialApp( title: 'Jetpack', theme: snapshot.data.themeData, home: PageHome(), routes: <String, WidgetBuilder>{ "/pageChatGroup": (context) => PageChatGroup(), "/LaoMeng": (context) => LaoMeng(), }, ); })AppTheme 是数据结构changeTheTheme 是算法StreamBuilder 是绑定UI这样一整套代码的逻辑就是我们所说的Flutter状态管理,这样解释大家理解了吗?再细说,算法就是我们如何管理,数据结构就是数据状态,状态管理的本质还是如何通过合理的算法管理数据,如何取,如何接收等,最终展示在UI上,通过UI的变更来体现状态的管理逻辑。 ...

May 26, 2020 · 5 min · jiezi