大佬们点波关注呀,从小家境贫寒,没见过四位数字,让我关注人数破千吧~
1.销毁和未创建调用
及时停止或者销毁监听,例如一个定时器:
Timer _countdownTimer;
@override
void dispose() {
_countdownTimer?.cancel();
_countdownTimer = null;
super.dispose();
}
为了保险我们还要在调用
setState()
前判断当前页面是否存在:
_countdownTimer = Timer.periodic(Duration(seconds: 2), (timer) {
if (mounted){
setState(() {
});
2.先绘制再请求
addPostFrameCallback
回调方法在Widget渲染完成时触发,所以一般我们在获取页面中的 Widget 大小、位置时使用到。
解决方法就是使用
addPostFrameCallback
回调方法,等待页面 build 完成后在请求数据:
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_){
/// 接口请求
}
3.保持页面状态
比如点击导航栏来回切换页面,默认情况下会丢失原页面状态,也就是每次切换都会重新初始化页面。这种情况解决方法就是
PageView
与
BottomNavigationBar
结合使用,同时子页面
State
中继承
AutomaticKeepAliveClientMixin
并重写
wantKeepAlive
为true。代码大致如下:
class _TestState extends State<Test> with AutomaticKeepAliveClientMixin{
@override
Widget build(BuildContext context) {
super.build(context);
return Container();
@override
bool get wantKeepAlive => true;
}
4.预先缓存图片
在 Flutter 中,加载本地图片会存在一个加载过程。比如点击图标做图标的切换时,那么首次会发生闪动的情况。尤其是做类似引导页这类需求是,通过左右滑动切换图片时会发生比较明显的白屏一闪而过。
解决方法很简单,就是使用
precacheImage
,它将图像预存到图像缓存中。如果图像稍后被 Image、BoxDecation 或 FadeInImage 使用,它会被加载得更快。
precacheImage(AssetImage("assets/logo"), context);
本问题详细的代码见:
点击查看
。
5.屏幕方向
新建的 Flutter 项目默认并没有限制屏幕的横竖屏,所以如果你的项目并没有适配横竖屏,需要限制某一方向。我以限制竖屏为例:
void main(){
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown
]).then((_){
runApp(MyApp());
}
6.FutureBuilder 懒加载
Flutter 中通过
FutureBuilder
或者
StreamBuilder
可以和简单的实现懒加载,通过
future
或者
stream
“异步” 获取数据,之后通过
AsyncSnapshot
的 data 再去加载数据,至于流和异步的概念,以后再展开吧。
const FutureBuilder({
Key key,
this.future,//获取数据的方法
this.initialData,
@required this.builder//根据快照的状态,返回不同的widget
}) : assert(builder != null),
super(key: key);
future 就是一个定义的异步操作,注意要带上泛型,不然后面拿去 snapshot.data 的时候结果是 dynamic 的 snapshot 就是 future 这个异步操作的状态快照,根据它的 connectionState 去加载不同的 widget 有四种快照的状态:
enum ConnectionState {
//future还未执行的快照状态
none,
//连接到一个异步操作,并且等待交互,一般在这种状态的时候,我们可以加载个菊花
waiting,
//连接到一个活跃的操作,比如stream流,会不断地返回值,并还没有结束,一般也是可以加载个菊花
active,
//异步操作执行结束,一般在这里可以去拿取异步操作执行的结果,并显示相应的布局
done,
}
7.StreamBuilder 流控制管理
从一端发射一个事件,从另外一端去监听事件的变化,通过 Stream 我们可以在 Flutter 上设计出基于事件流驱动的响应式代码逻辑。常用于会多次读取数据的异步任务场景,如网络内容下载、文件读写等。
class StreamDemo extends StatefulWidget {
@override
_StreamDemoState createState() => _StreamDemoState();
class _StreamDemoState extends State<StreamDemo> {
var index = 0;
var streamController;
StreamSink<String> get streamSink => streamController.sink;
Stream<String> get streamData => streamController.stream;
@override
void initState() {
super.initState();
streamController = StreamController<String>();
streamSink.add("0");
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('streamBuilder')),
body: StreamBuilder<String>(
stream: streamData,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
return Text('Result: ${snapshot.data}');
floatingActionButton: FloatingActionButton(
onPressed: onFloatActionButtonPress, child: Icon(Icons.add)));
void onFloatActionButtonPress() {
index++;
streamSink.add(index.toString());
}
8.Future 发起多个异步操作的方式
复杂耗时操作或者多个网络请求并对完整性要求较高的操作,可以使用
Future
异步方法:
Future.wait([
// 2秒后返回结果
Future.delayed(new Duration(seconds: 2), () {
return "hello";
// 4秒后返回结果
Future.delayed(new Duration(seconds: 4), () {
return " world";
]).then((results){
print(results[0]+results[1]);
}).catchError((e){
print(e);
});
9.Text 上下边距调整
左侧的彩色矩形是支柱(尽管实际上支柱没有宽度)。这个矩形的高度是最小的线条高度。这条线不能再短了。但它可以更高。
-
上升是从基线到文本顶部的距离(由字体定义,而不是任何特定的字形)
-
下降是从基线到文本底部的距离(由字体定义,而不是任何特定的字形)
前导(读作“ledding”,如旧排字机用来排字的铅字金属)是一行底端和下一行顶端之间的距离。在支柱中,一半的引线放在顶部,一半放在底部。是图中的灰色区域。 > 可以使用乘数更改支柱的垂直尺寸。
class TextLineHeight extends StatelessWidget {
final String textContent;
final double leading;
final double textLineHeight;
final double fontSize;
TextLineHeight({
this.textContent,
this.leading: 0,
this.textLineHeight: 0.93,
this.fontSize: 26,
@override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset(0, fontSize/11.52),
child: Text(
textContent,
strutStyle: StrutStyle(
forceStrutHeight: true,
height: textLineHeight,
leading: leading,
fontSize: fontSize,
style: TextStyle(
fontSize: fontSize,
color: Colors.black,
}
效果对比:
10.空判断
使用
null-aware operators
判断 null,减少代码量。
// User below
title ??= "Title";
// instead of
if (title == null) {
title = "Title";
}
上面的方法可以在只有一层判断中做保护,如果你有一连串的’.’取值,那就需要用这种方法了。
xxCount = xxModel?.xxInfo?.xxCount ?? 0
11.VSCode 配置项
{
"version": "0.2.0",
"configurations": [
"name": "Main",
"type": "dart",
"request": "launch",
"program": "lib/main.dart”,
"flutterMode": "profile" # 测试完后记得把它改回去!
"name": "Dev",
"type": "dart",
"request": "launch",
"program": "lib/main_dev.dart",
"args": [
"--flavor",
"universal",
"flutterMode": "profile" # 测试完后记得把它改回去!
"name": "Prod",
"type": "dart",
"request": "launch",
"program": "lib/main_prod.dart",
"args": [
"--flavor",
"universal",
重识Flutter 在不同的滑动列表场景,请选择合适的Slivers - part2
在Flutter中,碰到复杂的、不同的滑动业务场景,若是选择了一个合适的Slivers组件,那么我认为问题会变得简单!
37596
4、Flutter开发-导入并升级flutter-go示例
因Flutter升级,FlutterGo暂停维护,这里导入的项目只能切回到旧版本,这里为了适应新版本的Flutter和Dart,我们新建项目,升级flutter-go,并记录学习。
1、按照之前章节,新建一个flutter_go的Flutter项目,修改build.gradle文件
3、Flutter开发-创建第一个Flutter应用
1、打开Android Studio,所以在窗口选择Start a new Flutter project(如果没有这个选项,需要安装Flutter,步骤看上一章节)
【Flutter】插件包选择 ( 查看文档是否全面 | 查看插件包的更新版本次数 | 查看使用示例 | 查看 GitHub 项目的 Star Fork Issues )(一)
【Flutter】插件包选择 ( 查看文档是否全面 | 查看插件包的更新版本次数 | 查看使用示例 | 查看 GitHub 项目的 Star Fork Issues )(一)
【Flutter】插件包选择 ( 查看文档是否全面 | 查看插件包的更新版本次数 | 查看使用示例 | 查看 GitHub 项目的 Star Fork Issues )(二)
【Flutter】插件包选择 ( 查看文档是否全面 | 查看插件包的更新版本次数 | 查看使用示例 | 查看 GitHub 项目的 Star Fork Issues )(二)