Flutter项目结构和示例代码说明—初学者笔记

220 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情 

个人开发环境

1Flutter 版本:flutter_macos_3.0.5-stable
2Android StudioAndroid Studio Chipmunk | 2021.2.1 Patch 2
3MacOS Big Sur 11.1
4Project 使用 Android StudioFlutter 插件初始化

Flutter目录结构简介

当你通过 Android StudioIntelliJVSCode的Flutter插件创建完项目后,会生成下面的目录结构和文件。

image.png

在开始编码之前我们有必要先了解下项目结构文件的各个基本作用(毕竟Flutter的文件目录还是挺少的)

文件夹和文件简述

文件夹说明权重
android用于存放 Android 项目的工程文件,可通过 Android Studio 打开并编译代码重要
ios用于存放 iOS 项目的工程文件,可直接通过 Xcode 打开并编译打包重要
lib用于存放 Flutter 的项目代码,我们的 Dart 代码基本在这个目录下编写重要
test用于存放测试代码,主要用来测试某个功能代码或性能重要
windows用于存放桌面端相关的文件普通
build编译后生成的相关文件或换缓存普通
文件说明
flutter_app.iml用于配置项目工程文件的路径(一般不需要修改)
pubspec.lock该文件类似于 Ruby 的Gemfile.lock. 当前项目依赖的 packages 以及对应的版本
analysis_options.yaml用于配置分析器,它静态分析 Dart 代码以 检查错误、警告
pubspec.yaml用于配置项目的依赖库,它保存当前项目的配置信息
README.md用于介绍和说明项目的详细信息

好了,现在大概对 FLutter 的项目结构有一个基本的了解,后面随着学习的深入会调整项目的目录文件。

lib 下的 main 文件

创建完项目后 Flutter 会默认在 lib 目录下创建一个 main.dar 文件,里面的代码是一个简单的计数器。

注意,默认计数器示例中的代码,可能随着 Flutter 插件的版本而发生改变。

// main.dart 文件代码

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

// This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {

      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(

        title: Text(widget.title),
      ),
      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

效果如图所示

image.png

这个实例代码的功能非常简单,只要点击右下角的按钮,中间的数字就会一直累加。

代码分析

1. 导入 package

import 'package:flutter/material.dart';

说明:导入 Material UI 组件库依赖,后续开发基本都会使用到它。

2. 程序入口

void main() => runApp(MyApp());

这里使用了 Dart 语法的简写表达式,如果看不懂的话可能要去复习下 Dart 的语法。

main()函数是程序的执行入口,跟大部分的编程语言一样。

runApp() 需要传输一个 Widget 对象。

MyApp()是我们的要初始化的组件对象。

3. 应用代码

1. 根组件 MaterialApp 类

// 这个 widget 对象将作为你程序的根组件
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
  1. MyApp 类继承了 StatelessWidget 类,而 Flutter 的组件基本都是 widge 类继承的。
  2. 这里重写了 build 方法,Flutter 构建页面会默认调用 build 方法在,它决定了加载后要展示的UI,后面会大量重写继承了 widge 类的 build 方法。
  3. MaterialApp 对象一般定义为根组件,初始化界面。
  4. MaterialApp 参数 home 也是传递一个 widget 对象,显示主界面内容,这里使用的是 MyHomePage 类对象

2. Widget 类

//MyHomePage 类对象代码

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}
  1. StatefulWidget 类是一个有状态的 widget 组件,它在 widget 的整个生命周期里是可变的,而另一个 StatelessWidget类则是无状态的组件类。
  2. 这里重写了 createState 方法,并调用 _MyHomePageState()类,返回一个 State 状态类。

3. State 类

class _MyHomePageState extends State<MyHomePage> {
   #记录增加数的变量
  int _counter = 0;
  #一个简单的自增函数
  void _incrementCounter() {
    setState(() {

      _counter++;
    });
  }
  #重写了 build 方法
  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(

        title: Text(widget.title),
      ),
      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
  1. setState() 方法的作用是通知 Flutter 框架界面状态发生了变化,然后 Flutter 通过 build 方法来刷新界面
  2. 界面的实现代码在 build 中编写,State 类重写了 build 方法并返回了一个 Scaffold 类对象。
  3. Scaffold 也是一个 widget,它是一个页面脚手架,方面后面快速构建移动端的界面。
  4. body 参数为主要的显示内容,传递一个 widget。
  5. appBar 参数是一个顶部的导航栏,传递一个 widget。
  6. floatingActionButton 参数代表右下角的按钮,onPressed 表示绑定的按钮事件。

整个示例代码的流程为:

  1. 当按钮被点击后执行 floatingActionButton 绑定的 _incrementCounter 方法.
  2. _incrementCounter 方法自增变量+1 ,同时调用 setState 通知 Flutter 框架有状态发生变化,需要执行 build 方法刷新界面UI.
  3. 最终显示到界面上.