Flutter工程目录结构
flutter_app
-android -包含Android特定文件的Android子工程
-bulid -Android和iOS的构建产物
-iOS -包含iOS特定文件的iOS子工程
-lib -Flutter应用源文件目录
- main.dart -程序运行入口文件
-test -测试文件
-flutter_app_demo.iml -工程配置文件
-pubspec.lock -记录当前项目实际依赖信息的文件
-pinspec.yaml -管理第三方库及资源的配置文件
除了Flutter本身的代码、资源、依赖和配置之外、Flutter还包含了Android和iOS的工程目录。Flutter工程实际上就是一个同时内嵌了Android和iOS原生
子工程的父工程。我们在lib目录下进行Flutter代码的开发。而某些特殊场景下的原生功能,则在对应的Android和iOS工程中提供相应的代码实现。供对应的
Flutter代码引用。Flutter会将相关的依赖和构建产物注入这两个子工程,最终集成到各自的项目中,而我们开发的Flutter代码,最终则会以原生工程的形式
运行。
工程代码
从简单示例中,从基础的组件、布局到手势的监听、再到状态的改变、Flutter最核心的思想
第一部分是应用入口、应用结构以及页面结构、可以帮助你理解构建Flutter程序的基本结构和套路、
第二部分是页面布局、交互逻辑及状态管理、能够帮你理解Flutter页面是如何构建、如何响应交互、如何更新的、
代码分析
import 'pckage:flutter/material.dart'
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) => MaterialApp(home:MyHomePage(title:'Flutter Demo'));
}
class MyHomePage extends StatefulWidget {
MyHomePage{key key, this.title}):super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Widget build(BuildContext context) => {...};
}
在本例中、Flutter应用为MyApp类的一个实例、而MyApp类继承自StatelessWidget类,这也就意味着应用本身也是一个Widget、事实上、在Flutter中,Widget
是整个视图描述的基础、在Flutter的世界里,包括应用、视图、视图控制器、布局等在内的概念、都建立在Widget之上,Flutter的核心设计思想便是一切皆Widget。
Widget是组件视觉效果的封装、是UI界面的载体、因此我们还需要为她提供一个方法、来告诉Flutter框架如何构建UI界面、这个方法就是build。
在build方法中,我们通常通过对基础Widget进行相应的UI配置、或是组合各类基础Widget的方式进行UI的定制化、比如在MyApp中,我通过MaterialApp这个Flutter
App框架设置了应用首页、即MyHomePage、当然MaterialApp也是一个Widget。
MaterialApp类是对构建material设计风格应用的组件封装框架、里面还有很多可配置的属性、比如应用主题、应用名称、语言标识符、组件路由等。但是、这些配置
属性并不是本次分享的重点。
MyHomePage是应用的首页、继承自StatefulWidget类、这代表着它是一个有状态的Widget(Stateful Widget)。而_MyHomePageState就是它的状态、
虽然MyHomePageState类也是Widget、但与MyApp类不同的是、它并没有一个build方法去返回Widget、而是多了一个creatState方法返回MyHomePageState
对象、而build方法则包含在这个—_MyHomePageState类当中.
StatefulWidget 与 StatelessWidget的接口设计、为什么会有这样的区别、主要是因为Widget需要依据数据才能完成构建、对于StatefulWidget来说、其依
赖的数据在Widget生命周期中可能会频繁的发生变化、由State创建Widget、以数据驱动视图更新、而不是直接操作UI更新视觉属性、代码表达更精炼、逻辑更清晰。
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: Text('You have pushed the button this many times:$_counter')),
floatingActionButton:FloatingActionButton(onPressed: _incrementCounter)
);
}
}
_MyHomePageState 中创建的Widget Scaffold,是Material库中提供的页面布局结构、它包含了AppBar、Body、以及FloatingActionButton。
AppBar 是页面的导航栏、我们直接将 MyHomePage 中的title属性作为标题可使用、body则是一个Text组件、显示了一个根据_counter属性可变的文本“
You have pushed the button this many times:$_counter'.floatingActionButton,则是右下角的带+号悬浮按钮、我们将_incrementCounter
作为其点击处理函数。
_incrementCounter的实现很简单、使用setState方法区自增状态属性——counter.SetState方法是Flutter以数据驱动视图更新的关键函数、他会通知Flutter
框架、我这有状态发生了改变、赶紧刷新界面、而Flutter框架收到通知、会执行Widget的build方法、根据新的状态重新构建页面。
状态的更改一定要配合使用 setState、通过这个方法调用、Flutter会在底层标记Widget的状态、随后触发重建、如果只修改、不调用setState、Flutter框架
也不会感知到状态的变化、因此界面上也不会有任何改变、

MyApp为Flutter应用的运行实例、通过在main函数中调用runApp函数实现程序的入口、而应用的首页则为MyHomePage、一个拥有_MyHomePageState状态
的StatefulWidget。_MyHomePageState通过调用build方法、以相应的数据配置完成率包括导航栏、文本及按钮的页面视图的创建。
当按钮被点击后、其关联的控件函数——incrementCounter会触发调用。在这个函数中,通过调用setState方法、更新_counter属性的同时,也会通知Flutter框架
其状态发生变化、随后、Flutter会重新调用build方法、以新的数据配置重新构建_MyHomePageState的UI、最终完成页面的重新渲染、
Widget只是视图的'配置信息'、是数据的映射、是只读的、对于StatefulWidget而言、数据改变的时候、需要重新创建Widget去更新界面、就意味着Widget创建
销毁会非常频繁、
Flutter对此进行了优化、其框架内部会通过一个中间层去收敛上层UI配置对底层真实渲染的改动,从而达程度降低对真实渲染视图的修改。提高渲染效率、而不是上层
UI配置变了就需要销毁整个渲染视图树重建。
Widget仅是一个轻量级的数据配置存储结构。重新创建速度非常快。
Flutter采用声明式UI设计、只需要描述当前的UI状态(即State)即可、不同UI状态的视觉变更由Flutter在底层完成。声明式UI编程的好处是:可以让我们把
复杂的视图操作细节交给框架去完成、这样一来不仅可以提高我们的效率、也可以让我们专注于整个应用和页面的结构和功能。