前言
学习了近三周的 Flutter
,想着总结一下,但无奈 Flutter 知识点太多,从 Dart 语言到 Flutter 布局,基础Widget,列表,异步,网络编程及周边生态,有很多点可以细讲,以我现在的知识储备实在不想误人子弟,本文将会从一个Todolist小例子带你入门Flutter开发,而不是单纯的讲解API。
什么是Flutter
Flutter是一个由谷歌开发的开源移动应用软件开发工具包,用于为Android、iOS、Windows、Mac、Linux、Google Fuchsia开发应用。与 h5+混合开发(Uniapp)和JavaScript开发+原生渲染(React Navite)不一样,Flutter 的底层采用自绘UI+原生的方式,它的性能,开发效率方面都完胜前两者,并且在商业上得到了很好的应用,如闲鱼、淘宝物价版,西瓜视频都采用了Flutter进行开发。
在Flutter当中,一切变量都是 Object,万物皆是 Widget(参考了React组件的设计思想)。
开发TodoList
本文不会教你如何搭建开发环境,如果你想搭建,Flutter官网 讲的更加详细,我们可以直接访问 dartpad 这个网站直接开发Flutter ,如果你有兴趣,可以打开这个网站跟着我一起敲敲代码。
基本结构
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Center(child: Text('Hello, World!')),
);
}
}
运行效果:
代码解析:
import 'package:flutter/material.dart';
是使用Flutter组件必须要引入的,里面包含了 Text, Image, Center等基础组件等等。main
函数是Flutter 的入口函数,它使用runApp
运行了MyAPP
这个weiget。- 接下来我们定义了
MyApp
这个 weiget,重写了它的build
方法,使用了MaterialApp
这个入口 widget,定义了首页的样子。
MaterialApp还包含了title,routes等属性。
无状态StatelessWidget和有状态StatefulWidget
和React当中的有状态组件和无状态组件一样,有状态组件就是有单独的交互逻辑和业务数据,通过 setState
来更新,而无状态组件则没有这些,所有的数据都是由外部传进来。
开发Todo页面
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: TodoPage(),
);
}
}
// 新增代码
class TodoPage extends StatefulWidget {
TodoPage({Key key}) : super(key: key);
@override
_TodoPageState createState() => _TodoPageState();
}
class _TodoPageState extends State<TodoPage> {
@override
Widget build(BuildContext context) {
return Center(child: Text('Hello, World!'));
}
}
代码解析:
- 因为我们要有数据和交互逻辑,所以我们使用了
StatefulWidget
来创建一个有状态的TodoPage
widget。 - 首先我们使用
TodoPage
初始化一些入参以及继承父类的一些东西。 - 接着我们重写了
createState
这个方法,让它生成一个_TodoPageState
的数据。 - _TodoPageState 继承了 state,在里面可以定义一些可响应的变量。
脚手架Scaffold
class _TodoPageState extends State<TodoPage> {
@override
Widget build(BuildContext context) {
//新增代码,省略一些没变动代码。。。
return Scaffold(
appBar: AppBar(title: Text('todo list')),
body: Center(child: Text('Hello, World!'))
);
}
}
Scaffold有 appBar,drawer,bottomNavigationBar,body等属性,可以快速搭建一个页面结构
定义数据和Model
//新增代码
class TodoModel {
TodoModel({
this.id,
this.title,
this.complete = false,
});
int id;
String title;
bool complete;
}
class _TodoPageState extends State<TodoPage> {
//新增代码,省略一些没变动代码。。。
List<TodoModel> todos = [];
int id = 0;
//...
}
代码解析:
- 这里我们使用了 dart 中的 List 类型定义了
todos
变量,int 类型定义了个 id,更多dart类型看dart官方文档 TodoModel
这个是什么?如果你写过 Typescript,那你应该清楚了,TodoModel定义了 todos内部的结构类型,在我们使用了就可以有很方便的提示,以及一些类型检测功能。
构建输入框和列表
一个Todo应用,最基本的结构就是一个可输入的表单和一个展示todo的列表,在Flutter中,我们使用 TextField
这个widget来创建输入框,使用 ListView
来构建列表:
class _TodoPageState extends State<TodoPage> {
List<TodoModel> todos = [];
int id = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('todo list')),
body: Column(children: [
TextField(),
Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
TodoModel item = todos[index];
return ListTile(
title: Text(item.title),
);
},
itemCount: todos.length)),
])
);
}
}
代码解析:
Column
是纵向布局widget。- ListView 两个重要属性,
itemBuilder
和itemCount
,一个是返回构建列表项的元素,一个是列表的数量,组合就构成了一个可滚动的列表。 ListTile
和Text
注意:在使用Column时,经常会出现一些报错,那是因为Flutter容器的限制,在这个我们就使用 Expanded来包裹ListView,防止出现类似的错误。
添加Todo
class _TodoPageState extends State<TodoPage> {
//...
void addTodo(text) {
TodoModel item = TodoModel(
id: id++,
title: text,
complete: false,
);
setState(() {
_todos.add(item);
});
}
//新增代码,省略一些没变动代码。。。
TextField(onSubmitted: addTodo)
// ...
}
代码解析:
- 定义了一个添加 todo 的方法。
- TextField 提交事件绑定了addTodo方法。
删除Todo
class _TodoPageState extends State<TodoPage> {
//...
void deleteTodo(index) {
List newTodos = todos;
newTodos.remove(newTodos[index]);
setState(() {
todos = newTodos;
});
}
//新增代码,省略一些没变动代码。。。
ListTile(
title: Text(item.title),
trailing: InkWell(
onTap: () {
deleteTodo(index);
},
child: Icon(Icons.close)),
)
// ...
}
代码解析:
- 定义了
deleteTodo
删除todo的方法 - ListTitile新增 trailing 属性,子组件是一个InkWell,用来绑定删除事件,再下面就是一个Icon widget。
更新Todo
class _TodoPageState extends State<TodoPage> {
//...
void updateTodo(index) {
List<TodoModel> newTodo = todos;
TodoModel item = newTodo[index];
item.complete = !item.complete;
setState(() {
todos = newTodo;
});
}
//新增代码,省略一些没变动代码。。。
ListTile(
onTap: () {
updateTodo(index);
},
title: Text(
item.title,
style: TextStyle(
decoration: item.complete
? TextDecoration.lineThrough
: TextDecoration.none),
),
trailing: InkWell(
onTap: () {
deleteTodo(index);
},
child: Icon(Icons.close)),
)
// ...
}
代码解析:
- 定义
updateTodo
方法。 - 给 ListTile 绑定一个点击事件onTap,用来更新Todo。
- 给 title 的文本widget加上样式,如果它完成了就显示删除线,反之不显示。
完整代码
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: TodoPage(),
);
}
}
class TodoModel {
TodoModel({
this.id,
this.title,
this.complete = false,
});
int id;
String title;
bool complete;
}
class TodoPage extends StatefulWidget {
TodoPage({Key key}) : super(key: key);
@override
_TodoPageState createState() => _TodoPageState();
}
class _TodoPageState extends State<TodoPage> {
List<TodoModel> todos = [];
int id = 0;
void addTodo(text) {
TodoModel item = TodoModel(
id: id++,
title: text,
complete: false,
);
setState(() {
todos.add(item);
});
}
void deleteTodo(index) {
List newTodos = todos;
newTodos.remove(newTodos[index]);
setState(() {
todos = newTodos;
});
}
void updateTodo(index) {
List<TodoModel> newTodo = todos;
TodoModel item = newTodo[index];
item.complete = !item.complete;
setState(() {
todos = newTodo;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('todo list')),
body: Column(children: [
TextField(onSubmitted: addTodo),
Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
TodoModel item = todos[index];
return ListTile(
onTap: () {
updateTodo(index);
},
title: Text(
item.title,
style: TextStyle(
decoration: item.complete
? TextDecoration.lineThrough
: TextDecoration.none),
),
trailing: InkWell(
onTap: () {
deleteTodo(index);
},
child: Icon(Icons.close)),
);
},
itemCount: todos.length)),
]));
}
}
总结
本文我们制作了一个非常简陋的TodoList,实现了增删查改的功能,通过这个例子,我们学习到了Flutter基本结构,基本组件Text,Column,ListView,以及Dart函数,类型,model等基础。
在Flutter当中,还有一些重点本文没有提及,如路由管理,网络请求,异步编程,JSON解析,而这些都是开发项目必备的,在后续我会出个更加完善的教程,包括上面这些以及Flutter常用widget API的使用,Dart语言总结和开发当中遇到的一些坑,方便自己对Flutter知识点做个总结,也希望可以帮助到有兴趣学习Flutter的你,共勉!!!
评论(0)