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(代码片段

Flutter 布局备忘录

VIM 代码片段插件 ultisnips 使用教程

markdown 打字稿...编码说明,提示,作弊,指南,代码片段和教程文章