玖叶教程网

前端编程开发入门

Flutter:我是如何在一个小时内从头构建一个简单的 App

Hi,大家好,我是承香墨影!上周 Google 发布了 Flutter 的 Beta 版本,我想将会带起来一波程序员来研究它。今天分享的文章,就是一个基于 Flutter 的入门文章,作者还是一个学生,在阅读 Flutter 之后,简单的创建了自己的第一个 Flutter App。虽然很简单,但是依然说明 Flutter 的简洁和快速开发的能力,看看作者是这么做到的吧!

— 承香墨影

作者 | Norbert

翻译 | 承香墨影

授权 承香墨影 翻译并发布

概要

这是一个偶然的事件,我正在浏览我的 Youtube 的订阅内容,看到了很多关于 Flutter 的相关视频,这引起了我的兴趣。我很兴奋的开始阅读它的文档。

我喜欢的学习方式,是边动手边学习。阅读完几页文档并研究如何创建一个新的项目,我对自己尝试新东西,倍感信心。

App

正如你在 Gif 中看到的那样,这是一个非常基本的应用程序,但它仍然有一些让我觉得有趣的地方。

  • 它使用 Google Book Api 从数据库中读取书籍数据。

  • 在数据展示前,显示一个加载指示器。

  • 将书名和图像,都加载显示出来。

在传统的 Android App 中,这将需要几个类和不少代码。

而使用 Flutter,这个 App 有一个类和 129 行代码。包括一些引入语句和布局。

这一切,是不是听起来很棒?让我们开始吧!

开始

在我开始之前,我并不会详细的介绍这个 App 的所有细节,请务必查看示例代码以及文档,进行参考。

另外,整个 App 的代码(所有 129 行代码),都在 Github 上开源,我推荐你看看。

List<Book> _items = new List();final subject = new PublishSubject<String>();bool _isLoading = false;

在这个例子中,我们需要 3 个变量。

一个书本的列表,其中一般被定义成长这样:

class Book { String title,url; Book(this.title,this.url); }

一个 Public Subject,它是 RxDart 的一部分,而 RxDart 又是 Rx 的一个实现,我这里主要用它来监听 textChanged 事件。

还有一个变量,表示我们目前是否在等待服务端响应。

此外,用户界面包含三个主要元素。

  • 列表

  • 加载器。

  • 文本输入框。

我们将他们放在一起。

new TextField( decoration: new InputDecoration( hintText: 'Choose a book', ), onChanged: (string) => (subject.add(string)),),

关于这个地方的一个有趣的部分是 onChanged,在这里我们传递了一个 Lambda,它讲当前输入的文本添加到 subject 上,这使得我们可以在其他地方监听回调。

_isLoading? new CircularProgressIndicator(): new Container(),

如果当前出于加载状态,则显示进度条,否则显示一个空的容器。

new Expanded( child: new ListView.builder( padding: new EdgeInsets.all(8.0), itemCount: _items.length, itemBuilder: (BuildContext context, int index) { return new Card( child: new Padding( padding: new EdgeInsets.all(8.0), child: new Row( children: <Widget>[ _items[index].url != null? new Image.network(_items[index].url): new Container(), new Flexible( child: new Text(_items[index].title, maxLines: 10), ), ], ) ) ); }, ),),

该列表是一个基于索引的 ListView。而在其内部,我们布局了一个用于显示网络图片的 Image 以及一个用于显示书籍描述的 Text

逻辑代码

 @override void initState() { super.initState(); subject.stream.debounce(new Duration(milliseconds: 600)).listen(_textChanged); }

在这个 initState 方法中,我们使用流式编码来处理它的事件并消费它们。这样做是为了每次点键入文本的时候,不会立即向 Api 服务器发送请求,而是会在最后一次键入文本之后,等待 600ms,再将输入的字符串发送到 _textChange() 方法,这也是我们使用 Rx 的唯一原因。

 void _textChanged(String text) { if(text.isEmpty) { setState((){_isLoading = false;}); _clearList(); return; } setState((){_isLoading = true;}); _clearList(); http.get("https://www.xxx.com/books/v1/volumes?q=$text") .then((response) => response.body) .then(JSON.decode) .then((map) => map["items"]) .then((list) {list.forEach(_addBook);}) .catchError(_onError) .then((e){setState((){_isLoading = false;});}); } void _onError(dynamic d) { setState(() { _isLoading = false; }); } void _clearList() { setState(() { _items.clear(); }); }

所有的逻辑都在这里了。

首先说几点,如果 Text 是空的,我们不再加载并消除列表。

另外,如果我们获取到 Text 的内容,我们将开始加载并清除列表。

之后,我们向 Google Api 发出请求 volumes?q=$text ,其中 text 包含当前输入的字符串。

当结果返回的时候:

  • 获得返回的内容。

  • 解析 JSON 数据,饭后返回一个 Map。

  • "items" 包含大量的书籍信息。

  • 循环迭代之后,使用 _addBook() 方法添加到 "items" 中。

  • 这些 "items" 就是我们需要的标题和书籍封面图。

 void _addBook(dynamic book) { setState(() { _items.add(new Book(book["volumeInfo"]["title"], book["volumeInfo"]["imageLinks"]["smallThumbnail"])); }); }

小结

到这里,该 App 是一个完整的小应用。

这是第一步,接下来将使用一个数据库来存储数据。

  • 我读过这本书吗?

  • 关于这本书的一些笔记内容。

期待你的持续关注。

在头条号私信我。我会送你一些我整理的学习资料,包含:Android反编译、算法、设计模式、虚拟机、Linux、Kotlin、Python、爬虫、Web项目源码。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言