大佬们点波关注呀,从小家境贫寒,没见过四位数字,让我关注人数破千吧~


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 中,加载本地图片会存在一个加载过程。比如点击图标做图标的切换时,那么首次会发生闪动的情况。尤其是做类似引导页这类需求是,通过左右滑动切换图片时会发生比较明显的白屏一闪而过。


image.png


解决方法很简单,就是使用 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 上下边距调整


image.png


左侧的彩色矩形是支柱(尽管实际上支柱没有宽度)。这个矩形的高度是最小的线条高度。这条线不能再短了。但它可以更高。

  • 上升是从基线到文本顶部的距离(由字体定义,而不是任何特定的字形)
  • 下降是从基线到文本底部的距离(由字体定义,而不是任何特定的字形)

前导(读作“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,
}

效果对比:


image.png


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 )(二)