likes
comments
collection
share

Flutter入门概览1-Flutter篇

作者站长头像
站长
· 阅读数 32

本系列文章共有三篇,计划分别从Flutter、Dart、工具三个方面介绍,快速形成对Flutter开发的一个综合概念。

本文主要介绍Flutter相关知识。

Flutter语言使用 Dart,开发IDE使用VSCode、Android Studio 或 IntelliJ IDEA,个人推荐使用VSCode。

Flutter概览

Flutter是由Google开发的开源移动应用开发框架,用于快速构建高性能、高保真度的跨平台移动应用。Flutter支持同一套代码在 iOS、Android、Web、桌面应用等多个平台上运行,使用自带的 Skia 图形引擎,可以直接绘制 UI 组件,这使得 Flutter 应用在性能方面表现出色,滚动流畅,响应迅速(目前正在使用 Impeller 替换 Skia)。

Flutter架构

Flutter入门概览1-Flutter篇

看一眼有个印象即可。

参考资料

三棵树

Flutter的渲染机制由三棵树组成:Widget Tree、Element Tree、Render Tree(渲染树)。

Flutter入门概览1-Flutter篇

  1. 所有Widget组成Widget Tree。
  2. 通过调用Widget的createElement()方法,创建Element Tree,Wdiget Tree与Element Tree是一一对应的。
  3. 每个Element调用 createRenderObject()形成Render Tree,Render Tree负责渲染,注意Render Tree与Elemeng Tree并不是一一对应的,而是为最后渲染做准备。

Widget

在Flutter中,widget是一个非常重要的概念,是描述UI的基本元素。可以用iOS中的UIView来类比理解widget的概念,但是widget并不是UIView。widget只是对布局的一种描述,最终还要经过三棵树生成element和renderObject才会被绘制到屏幕上,而UIView就是最终渲染的view。

这里可以给出一个widget的定义:widget是Flutter中描述一UI元素的配置信息,需要经过三棵树生成最终的renderObject才会被渲染到屏幕上。可以用UIView理解,但是UIView更像renderObject。

在Flutter中,通过widget嵌套widget的方式来构建UI和进行事件处理,所以万物都是Widget。Widget的基类是Widget,是一个抽象类一般不会直接用。

在flutter中,widget分为两类:有状态的widget和无状态的widget,即StatefulWidgetStatelessWidget,两个都直接继承自Widget类。不需要改变的元素使用StatelessWidget,设定好后元素不会被改变;需要改变的元素需要使用 StatefulWidget,通过改变内部state来修改自身UI,触发重新渲染。

  • StatelessWidget,无状态widget,设定好后不能再修改。
  • StatefulWidget,有状态的widget,内部会对应一个State类,通过修改State可以改变自身widget,然后更新UI。

参考:

StatelessWidget

StatelessWidget是无状态组件,通过build方法来构建UI。

  • build,通过build方法嵌套其他widget来构建UI,在构建过程中会递归的构建其他嵌套的widget。
  • contextbuild方法有一个context参数,它是BuildContext类的一个实例,表示当前 widget 在 widget 树中的上下文,每一个 widget 都会对应一个 context 对象(因为每一个 widget 都是 widget 树上的一个节点)。实际上,context是当前 widget 在 widget 树中位置中执行”相关操作“的一个句柄(handle),比如它提供了从当前 widget 开始向上遍历 widget 树以及按照 widget 类型查找父级 widget 的方法。
// StatelessWidget 定义
abstract class StatelessWidget extends Widget {
  const StatelessWidget({ super.key });

  @override
  StatelessElement createElement() => StatelessElement(this);
  
  // 核心是 build 方法
  @protected
  Widget build(BuildContext context);
}

// 示例,Echo widget,核心是build方法构建UI
class Echo extends StatelessWidget  {
  const Echo({
    Key? key,  
    required this.text,
    this.backgroundColor = Colors.grey, //默认为灰色
  }):super(key:key);
    
  final String text;
  final Color backgroundColor;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: backgroundColor,
        child: Text(text),
      ),
    );
  }
}



// 在子树中获取父级widget的一个示例:
class ContextRoute extends StatelessWidget  {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Context测试"),
      ),
      body: Container(
        child: Builder(builder: (context) {
          // 在 widget 树中向上查找最近的父级`Scaffold`  widget 
          Scaffold scaffold = context.findAncestorWidgetOfExactType<Scaffold>();
          // 直接返回 AppBar的title, 此处实际上是Text("Context测试")
          return (scaffold.appBar as AppBar).title;
        }),
      ),
    );
  }
}

StatefulWidget

StatefulWidget的核心就是有状态,可以修改重绘UI。

  • StatefulWidget重写了createElement方法,返回的是StatefulElementStatefulElement可能会多次调用createState()来创建对象。
  • createState(),创建状态,修改UI必须通过修改状态来实现,一个StatefulElement对应一个State实例。
abstract class StatefulWidget extends Widget {
  const StatefulWidget({ Key key }) : super(key: key);
    
  @override
  StatefulElement createElement() => StatefulElement(this);
    
  @protected
  State createState();
}

State

一个StatefulWidget类会对应一个State类,State表示与其对应的StatefulWidget要维护的状态。

State中的状态信息:

  1. 在 widget 构建时可以被同步读取。
  2. 在 widget 生命周期中可以被改变,当State被改变时,可以手动调用其setState()方法通知Flutter 框架状态发生改变,Flutter 框架在收到消息后,会重新调用其build方法重新构建 widget 树,从而达到更新UI的目的。

State中有两个常用的信息:

  1. widget,它表示与该 State 实例关联的 widget 实例,由Flutter 框架动态设置。注意,这种关联并非永久的,因为在应用生命周期中,UI树上的某一个节点的 widget 实例在重新构建时可能会变化,但State实例只会在第一次插入到树中时被创建,当在重新构建时,如果 widget 被修改了,Flutter 框架会动态设置State. widget 为新的 widget 实例。
  2. context。StatefulWidget对应的 BuildContext,作用同StatelessWidget 的BuildContext。

State生命周期:

Flutter入门概览1-Flutter篇

这块详细参考:State-Flutter实战第二版

参考资料

布局

Debugger输出

  • debugPrint
  • Print
  • log
// debugPrint
import 'package:flutter/foundation.dart';、
debugPrint('movieTitle: $movieTitle');

// log
import 'dart:developer';  //(auto import will do this even)
//example for api logging
log("${response?.statusCode} :  ${response?.request?.path}",
          name: "Response", error: response.data);

Flutter命令

// 检测flutter配置,输出相关依赖的安装情况
flutter doctor

// flutter 工程安装依赖,注意针对flutter工程,需要使用flutter命令(dart pub get是针对dart工程)
flutter pub get


// flutter 工程添加依赖
flutter pub add css_colors

// flutter 移除依赖
flutter pub remove css_colors

// 运行flutter工程
flutter run

// Other
// 升级Flutter SDK
flutter upgrade

// 创建Flutter App
flutter create test_drive // 创建Flutter工程模板
flutter devices // 选择对应的平台
flutter run // 运行Flutter工程

// 后续注意使用 fvm flutter 代替 flutter
# Use
> fvm flutter {command}
# Instead of
> flutter {command}

// 后续使用 fvm dart 代替 dart
# Use
> fvm dart {command}
# Instead of
> dart {command}


创建Flutter工程

具体参考:开发体验初探

通过VSCode创建Flutter App:

  • 打开VSCode命令窗口,输入Flutter,选择Flutter: New Project Flutter入门概览1-Flutter篇
  • 通过命令行创建 :flutter create -t app

Flutter工程结构目录

工程结构

创建工程后,默认会显示以下文件

.
├── .dart_tool    # 记录了一些dart工具库所在的位置和信息
├── .idea      # android studio 是基于idea开发的,.idea 记录了项目的一些文件的变更记录
├── android      # Android项目文件夹
├── build      # 编译或运行后产物
├── ios        # iOS项目文件夹
├── lib        # lib文件夹存放我们的dart语言代码
├── linux      # Linux项目目录
├── macos      # mac项目目录
├── test      # 测试代码
├── web        # web项目目录
├── windows      # win项目目录
├── .gitignore    # git忽略配置文件
├── .metadata    # 一个对当前workspace的配置记录
├── analysis_options.yaml      # flutter lint配置文件,定义代码静态分析相关的配置项和规则
├── flutter_application_1.iml    # 工程文件的本地路径配置,在Android Studio或IntelliJ下起作用
├── pubspec.lock          # 项目依赖的lock文件
├── pubspec.yaml          # 依赖配置文件,类似package.json文件
└── README.md             # README

其中比较关注以下几个文件夹:

  • lib,存放工程的核心代码
  • pubspec.yaml,依赖配置管理

另外,一般额外创建两个目录:assetsfonts,用于存放图片和字体,注意需要在pubspec.yaml文件中声明。

# 示例
# The following section is specific to Flutter.
flutter:

  # To add assets to your application, add an assets section, like this:
  assets:
    - assets/images/

  fonts:
    - family: Raleway
      fonts:
        - asset: fonts/Raleway-Regular.ttf
        - asset: fonts/Raleway-Italic.ttf
          style: italic
    - family: RobotoMono
      fonts:
        - asset: fonts/RobotoMono-Regular.ttf
        - asset: fonts/RobotoMono-Bold.ttf
          weight: 700

lib目录结构

不要一直寻求最佳实践,最佳实践只是最小省力原则,要 go above and beyond。

lib目录是存放了我们工程代码,结合前端工程,目前得出一个最佳目录结构。

lib
├── main.dart
├── api # 接口请求
├── components # 公共组件
├── l10n # 国际化,Flutter中使用 flutter_localizations 库作为国际化,因此叫l10n
├── router # 路由
├── store # 状态管理
├── models    # Json文件对应的Dart Model类会在此目录下
├── types # 公共类型定义
├── utils # 工具函数、通用方法、网络接口
└── pages # 页面

参考:

pubspec.yaml文件

参考资料

常用三方库

功能类

工具类

  • mason,文件模板生成器,方便做脚手架用
  • melos,Flutter的Monorepo管理工具
  • freezed,一个用于数据类 / 联合体 / 模式匹配 / 克隆的代码生成器

学习Demo

FlutterUnit

FlutterUnit是一个非常强大的Flutter学习利器,提供全面的Flutter学习指南,支持iPhone/Andriod/Mac/PC全平台,可以快速查看组件API说明和示例。可以说是学习Flutter的必备学习软件。

Flutter源码中的可用的组件一共350个左右,纷繁复杂,也没有明确的分类标准 FlutterUnit 对大大小小,常用不常用的组件能收的尽量收录。并根据个人感觉进行评星 目前收录组件306个,每个都有至少一个演示展现和代码展示。

FlutterUnit提供以下功能:

  • 300+组件的收录
  • 组件详情说明,提供组件的属性和说明演示
  • 可操作,操作交互类组件提供可操作性
  • 提供组件的关联切换

Flutter入门概览1-Flutter篇

Flutter入门概览1-Flutter篇

Material Design

是一种用户界面设计语言,开始被Google引入用于安卓的UI设计风格。现在提供一系列UI组件,Flutter核心的UI库。

参考资料:

参考资料

转载自:https://juejin.cn/post/7376937268215463975
评论
请登录