Flutter教程2
Posted 你倾城一笑惊绝了多少年华
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter教程2相关的知识,希望对你有一定的参考价值。
给IDE安装插件
我使用vsCode,安装Futter和Dart两个插件,你也可以使用android Studio IDE或者IntelliJ,也需要安装插件。
创建一个基于模版的Flutter app
在你的项目文件夹下打开终端,输入 flutter create 你的app名称。
比如 cd Desktop/www && flutter create firstapp
。
用IDE打开项目,你主要编辑的是 lib/main.dart
文件。
Hello World
按照惯例,我们写一个 Hello World。
首先删除 lib/main.dart
内的内容,然后输入
import 'package:flutter/material.dart';
void main() => runApp(new Center(
child: new Text('Hello World', textDirection: TextDirection.ltr),
));
终端运行 flutter run,
效果如下图
1. 代码中使用了runApp函数,runApp函数接受指定的控件(Widget),并使其作为控件树(widget tree)的根控件。控件(Widget)定义一个元素(Element)的配置,在Flutter框架的层次结构中处于核心层。本实例中,控件树(widget tree)包含两个控件,Center控件使其子控件处于中间位置,Text控件打印文本内容。runApp函数强制将根控件覆盖屏幕,这意味着文本将显示在屏幕中心。
2. main函数使用了(=>)符号, 这是Dart中单行函数或方法的简写。
3. import 'package:flutter/material.dart',引入Flutter提供的一套丰富的Material widgets。
创建一个书单列表应用
1. 定义一个展示类 Book.dart
import 'package:flutter/material.dart';
// 声明一个 Book 类
class Book {
// 声明一个常量构造函数
const Book({this.name});
final String name;
}
// 重命名一个具有两个参数的来自父控件的回调函数CartChangedCallback,两参数分别为自定义的Book类和布尔型,
typedef void CartChangedCallback(Book book, bool inCart);
// 定义一个扩展自Flutter无状态组件的类 BookItem
class BookItem extends StatelessWidget {
// 声明构造函数,并调用超类为每一个book实例增加一个key
BookItem({Book book, this.inCart, this.onCartChanged})
: book = book,
super(key: new ObjectKey(book));
final Book book;
final bool inCart;
final CartChangedCallback onCartChanged;
// 定义一个颜色方法
Color _getColor(BuildContext context) {
return inCart ? Colors.black54 : Theme.of(context).primaryColor;
}
// 定义一个文本样式方法
TextStyle _getTextStyle(BuildContext context) {
if (!inCart) return null;
return new TextStyle(
color: Colors.black54,
decoration: TextDecoration.lineThrough,
);
}
// 重写一个 Widget
@override
Widget build(BuildContext context) {
return new ListTile(
onTap: () => onCartChanged(book, !inCart),
leading: new CircleAvatar(
backgroundColor: _getColor(context),
child: new Text(book.name[0]),
),
title: new Text(book.name, style: _getTextStyle(context)),
);
}
}
BookItem控件遵循无状态控件的通用模式,将在构造函数中接收到的值存储在final成员变量中,然后在build函数执行时使用。
当用户点击列表项时,控件不会直接修改inCart的值,但是控件从父控件接收onCartChanged函数。此模式允许你在控件较高的层次结构中存储状态,这样使状态的持续时间更长。在极端情况下,存储在runApp的控件状态在应用程序的生命周期内保持不变。
当父控件接收到onCartChanged回调,父控件会更新其内部状态,这将触发父控件重建并使用新的inCart值创建BookItem的新实例。尽管父控件在重建时创建了BookItem的新实例,但该操作很节省,因为框架会将新构建的控件与之前构建的控件时进行比较,并将有差异的部分应用于底层渲染对象。
2. 编写父控件 mian.dart
import 'package:flutter/material.dart';
// 引入Book.dart
import 'Book.dart';
// 定义一个扩展自有状态控件的 BookList 类
class BookList extends StatefulWidget {
BookList({Key key, this.books})
: super(key: key);
final List<Book> books;
@override
_BookListState createState() => new _BookListState();
}
class _BookListState extends State<BookList> {
Set<Book> _bookCart = new Set<Book>();
void _handleCartChanged(Book book, bool inCart) {
setState(
() {
if (inCart)
_bookCart.add(book);
else
_bookCart.remove(book);
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('书单列表'),
),
body: new ListView(
children: widget.books.map(
(Book book) {
return new BookItem(
book: book,
inCart: _bookCart.contains(book),
onCartChanged: _handleCartChanged,
);
}
).toList(),
),
);
}
}
final List<Book> _kBooks = <Book>[
new Book(name: '你倾城一笑惊绝了多少年华'),
new Book(name: '她被你一笑绝经了多少年头'),
new Book(name: '我看你俩是昏厥了多少岁月'),
new Book(name: '他看着我们懵逼了多少时光'),
new Book(name: '所有人梦里花落了多少年少'),
];
void main() => runApp(new MaterialApp(
title: '我的应用',
home: new BookList(books: _kBooks),
));
类BookList继承了StatefulWidget,这意味着这个控件存储可变状态,当BookList首次插入到树中,框架调用createState函数在树中相关联的位置创建一个新的_BookListState实例。当该控件的父控件重建时,父控件会创建一个新的BookList实例,但框架将重用已经在树上的_BookListState实例,而不会再次调用createState函数。
要访问当前BookList的属性,_BookListState可以使用其config属性。如果父控件重建并创建一个新的BookList,_BookListState也将使用新的config值重建。如果想要在config属性更改时收到通知,可以覆盖didUpdateConfig函数,它通过oldConfig将旧配置与当前config进行比较。
当处理onCartChanged回调时,_BookListState通过从_bookCart中添加或删除一个产品来改变其内部状态。为了向框架通知它改变了内部状态,它在setState中封装这些调用。调用setState将控件标记为dirty,并安排它在应用程序下次需要更新屏幕时重建。如果在修改控件内部状态时忘记调用setState,框架不会知道控件是dirty的,可能不会调用控件的build函数,这意味着用户界面不会更新以反映更改的状态。
通过这种方式管理动态,不再需要单独编写代码来创建和更新子控件。相反,只需要实现构建函数,即可处理这两种情况。
以下是最终效果图
以上是关于Flutter教程2的主要内容,如果未能解决你的问题,请参考以下文章
Flutterflutter doctor 报错Android license status unknown. Run `flutter doctor --android-licenses‘(代码片段
flutter解决 dart:html 只支持 flutter_web 其他平台编译报错 Avoid using web-only libraries outside Flutter web(代码片段
Flutter 报错 DioError [DioErrorType.DEFAULT]: Bad state: Insecure HTTP is not allowed by platform(代码片段