likes
comments
collection
share

Flutter 项目结构 初始项目 分析

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

本文主要讲述新建一个Flutter项目的各个项目结构,并配合初始项目,来了解Flutter的各种状态,以及常用类解析

项目结构解析,以及各个文件的作用

新创建一个Flutter项目,项目接口如下图所示

Flutter 项目结构 初始项目 分析

  • .drat_toolFlutter工具使用的一个临时目录,包含了一些工具生成的配置和构建输出。一般不需要开发者去修改,由Flutter自动生成
  • .idea idea的配置信息,不用管
  • android 存放Android平台相关的代码和配置文件,一般需要修改的是AndroidManifest.xml,用来配置权限和注册文件的
  • build 编译文件 不用管
  • ios 这个目录是用于存放iOS平台相关的代码和配置文件的
  • lib 这个目录是主要的Dart目录,用来存放应用程序的逻辑和界面代码,大部分开发会在这个目录下进行
  • linux 这个目录是用于存放Linux平台相关的代码和配置文件的。它包含了一个Linux项目的结构,其中包括CMake构建脚本和其他与Linux相关的资源和配置文件。
  • macos 这个目录是用于存放macOS平台相关的代码和配置文件的。
  • test 编写测试文件
  • web 这个目录是用于存放Web平台相关的代码和配置文件的
  • windows 这个目录是用于存放Windows平台相关的代码和配置文件的
  • .gitignore 配置git上传的
  • .metadata 文件是由Dart编译器生成的元数据文件。它包含有关项目的编译和依赖信息。遇到meadata报错怎么办,嗯,删掉,让Dart重新编译
  • analysis_options.yaml 配置静态代码分析工具,可以在这里定义代码风格,金庸或启用特定的警告和错误检查之类
  • pubspec.ymal 配置文件,用于声明项目的依赖关系、资源我呢见、版本号信息等,类似于Androidbuild文件
  • ubspec.lock 自动生成,锁定项目的依赖关系

其中pubspec.yaml是必需的,用于配置项目的依赖和资源,而pubspec.lockanalysis_options.yaml是根据需要自动生成的辅助文件,所以详细说一下pubspec.yaml文件

pubspec.yaml文件解析

这一段需要配合 着代码看

name: untitled   #项目名称
description: A new Flutter project.   #项目描述

publish_to: 'none'    #防止上传到pub.dev   这个类似与maven


version: 1.0.0+1    #版本号  前面是版本名字 +1是第一个版本

environment:
  sdk: '>=3.0.1 <4.0.0'   # 设置最低和最高版本

dependencies: #依赖文件 外部包
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2
  http: ^1.0.0   #把http 1.0.0版本导入项目


dev_dependencies: #开发时期的依赖包 通常是测试框架之类
  flutter_test:
    sdk: flutter

  flutter_lints: ^2.0.0


flutter: #包含Flutter特定字段   ,比如配置
  uses-material-design: true
  assets:
    - assets/

这一段把创建项目的注释去掉 翻译一下大概就是这个意思,值得注意的是flutter这个内容下uses-material-design的意思是是 是否使用了Material Design 风格,assets下面这个表示把assets这个文件夹加载进去,一般就是系统资源,比如本地图片,如果在使用,必须先加载,我这里是把一个文件夹都加载了进去,当然也可以一个以额添加,路径copy上去就可以

初始项目解析

在创建Flutter项目的时候有一个默认的计数器的Demo,我们就以此Demo来看一下他们分别有什么用

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

一个应用的入口,可以理解为Activity + 多Fragment形式,MyApp就相当于第一个Fragment,然后进入执行了MyApp一个类

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.orange),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

为什么要继承StatelessWidget我当时也思索一段时间,也配合了文档和资料总结了一下,以下是我的理解: 常用的一般有StatelessWidgetStatefulWidget用来构建用户界面

  • StatelessWidget 是一个不可变部件,它的外观和交互在构建期间就确定了,不会发生变化,适用于那些不需要管理可变状态的部件,通常用于显示静态内容、接收用户输入并触发回调等简单场景。
  • StatefulWidget 是一个可变部件,它可以根据内部的状态数据来改变外观和交互,适用于那些需要动态更新、管理状态的部件,例如表单输入、列表视图等。 也就是说主要看页面需不需要和用户互动,需要就用StatefulWidget,不需要就用StatelessWidget 然后MaterialApp是一个页面框架,可以设置主题,相当于Android的Theme,以及使用应用Material3

然后Home现在了一个MyHomePage,这里又出现了一个const什么意思呢,从经验来说一个常量,为什么要用常量来修饰小组件呢,因为小组件是不可变的,也就告诉编译器说这个小组件运行是不会发生变化,在重新渲染的时候可以直接使用,那MyHomePage里面可能会有变化啊,这里指的变化是不会从MyHomePage变成其他的Page

好的 来看下一段

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

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Image.asset('assets/icon.png'),
            ),
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

这里就相当于是显示的核心,等等为什么要分两个类写,我写个匿名内部类不完了吗,这里分开写的解释为最重要的一点性能问题,如果都写到一起,协程匿名内部类,当状态发生变化时,所有的外观和交互逻辑都会被重新构造和渲染,带来性能问题,分开写其他的好处就是,解耦啦,可读性啦,可重用性啦.....

分析完成之后学习以下控件吧

  • Scaffold 一个模板,就他把样式位置给你调整好,你写参数就完事
  • Center 显示到界面中间 类似于Android FrameLayoutgravity
  • Column 竖直盘列小组件 类似于Android LinearLayoutvertical
  • padding 设置内边距 这个和AndroidView不同,需要单独加一个小组件,而不是直接对View设置
  • Text 用来显示文本,相当于TextView 没什么好说的
  • FloatingActionButton 就是右下角的按钮 Android也有类似的,这里注意的是 定位是Scaffold赋予它到这个位置的,然后点击时间为onPressedonClick一样,这里和Kotlin的点击回调很类似啊,调用了一个_incrementCounter方法

这里需要说一句 _incrementCounter 方法里面有一个setState 的方法 然后因为要告诉Flutter我这个页面发生变化了,setState就是这样的作用

总结

这一章算是学习了一下Flutter的基础示例项目,因为本人也是Android开发工程师,最近也是空闲时间比较多,所以有了学习Flutter的念头,其中有问题的地方,麻烦大佬指出来,方便及时修改,在这里感激不尽,还有一个就是学习方式的问题,我可能比较喜欢配合着官方的示例项目一个一个来看,然后不懂了看文档,看别人写的文章,所以每一下子把小组件介绍完,那样我也记不住,另外Dart语音和Java很相似,又有一些Kotlin的小玩意,因为本人是都学习还可以,所以不太吃力语言方面,不会的可以找Dart语法看一看