前言
本文是一个纯Flutter项目,主要通过实现网络请求新闻表展示以及跳转webview详情页,来初步感受了一下最近很火的Flutter
代码在 源码地址 部分代码参考 https://github.com/zhangjianli/flutter_news
安装环境
可以参考 Flutter中文网 我使用的是AndroidStudio,这里需要注意的是下载下来的flutter sdk 在会自动下载dart sdk 具体在 flutter/bin/cache/dark-sdk往往在导入新工程时候需要设置dart sdk 注意设置一下就好
Dart
Flutter的开发语言采用Dart,这是一门很棒的语言,集合了现代语言的很多优点,学习了一下之后感觉有java的影子,也有es6的影子,写起来很简练,Dart有个官方学习网站
Flutter之布局
比如实现一个如下的布局
1 | class _MyHomePageState extends State<MyHomePage> { |
乍一看其实挺懵逼的,
要记住一点在Flutter中一切皆为’Widget‘,在flutter的世界里,包括views,view controllers,layouts等在内的概念都建立在Widget之上。widget是flutter功能的抽象描述,掌握Flutter的基础就是学会使用widget开始甚至一个padding就是一个widget,官网是按照子元素来分类的
- 单个子元素(child)的布局,包括Container、Padding等
18
种(目前是2018年12月1日,后续我想肯定会增加的); - 多个子元素(children)的布局,包括Row、Column等
11
种; - layout helper,例如ListView.Builder,在元素多的时候,用这种方式更加的高效,类似Android的RecyclerView,有自动的回收机制。这种严格意义上不能算是一个种类,我觉得这种helper会越来越多。
常见有的其中常用有 Container、Padding、Center、Flex、Stack、Row、Column、ListView 等
类型 | 特点 |
Container | 只有一个子 Widget。默认充满,包含了padding、margin、color、宽高、decoration 等配置。 |
Padding | 只有一个子 Widget。只用于设置Padding,常用于嵌套child,给child设置padding。 |
Center | 只有一个子 Widget。只用于居中显示,常用于嵌套child,给child设置居中。 |
Expanded | 只有一个子 Widget。在 Column 和 Row 中充满。 |
Stack | 可以有多个子 Widget。 子Widget堆叠在一起。 (类似Android的 FrameLayout) |
Column | 可以有多个子 Widget。垂直布局。 (类似Android的 LinearLayout vertical) |
Row | 可以有多个子 Widget。水平布局。 (类似Android的 LinearLayout horizon) |
这布局写起来确实很酸爽,不过统一渲染效率更高,但是掌握起来比较费事,感觉平台侧的一些成本转嫁到开发者身上,不知道后期有没有类似xml这种布局单独剥离出来的实现。
widget详解
一切皆为widget,主要分为两类 StatefulWidget(有状态)和 StatelessWidget(无状态)
- StatefulWidget(有状态)
如果一个控件需要动态的去改变或者相应一些状态,例如点击态、色值、内容区域等,那么一般都是继承自StatefulWidget,常见的有CheckBox、AppBar、TabBar等 - StatelessWidget(无状态)
如果一个控件自身状态不会去改变,创建了就直接显示,不会有色值、大小或者其他属性的变化,这种widget一般都是继承自StatelessWidget,常见的有Container、ScrollView等
StatefulWidget和StatelessWidget如下所示
一个StatelessWidget可以用多个不同的BuildContext构建,而一个StatefulWidget会为每个BuildContext创建一个State对象
对于StatelessWidget,build方法会在如下三种情况下调用,
- widget第一次被插入到树中;
- widget的父节点更改了配置(configuration);
- widget依赖的InheritedWidget改变了;
1 | class Frog extends StatelessWidget { |
StatefulWidget的两个主要类别:
- 在initState中创建资源,在dispose中销毁,但是不依赖于InheritedWidget或者调用setState方法,这类widget基本上用在一个应用或者页面的root;
- 使用setState或者依赖于InheritedWidget,这种会在生命周期中会被重建(rebuild)很多次。
1 | class YellowBird extends StatefulWidget { |
State
状态有何作用呢
- 在widget构建的时候可以被同步读取;
在widget的生命周期中可能会被改变。
State生命周期
对应的生命周期如下
created:当State对象被创建时候,State.initState方法会被调用;
- initialized:当State对象被创建,但还没有准备构建时,State.didChangeDependencies在这个时候会被调用;
- ready:State对象已经准备好了构建,State.dispose没有被调用的时候;
- defunct:State.dispose被调用后,State对象不能够被构建
完整生命周期如下:
- 创建一个State对象时,会调用StatefulWidget.createState;
- 和一个BuildContext相关联,可以认为被加载了(mounted);
- 调用initState;
- 调用didChangeDependencies;
- 经过上述步骤,State对象被完全的初始化了,调用build;
- 如果有需要,会调用didUpdateWidget;
- 如果处在开发模式,热加载会调用reassemble;
- 如果它的子树(subtree)包含需要被移除的State对象,会调用deactivate;
- 调用dispose,State对象以后都不会被构建;
- 当调用了dispose,State对象处于未加载(unmounted),已经被dispose的State对象没有办法被重新加载(remount)。
setState
当修改状态时,调用setState widget会被更新
如何布局
每个页面设计都不一样,相同页面可选择的布局方式也不一样,可以参考下Flutter官方的布局教程。整个过程,基本上按照拆解、组件封装、具体布局这三步来的。
Flutter之网络请求
在Android开发者我们可以使用okHttp,Flutter给我们封装好了,在pubspec.yaml文件中接入网络依赖库,相当于gradle的dependency,可以在 包查找 中找到最新版本,在pubspec.yaml接入时候主要空格就好1
2
3
4
5
6
7
8
9
10
11dependencies:
flutter:
sdk: flutter
json_annotation: ^2.0.0
flutter_webview_plugin: ^0.3.0+2
http: ^0.12.0
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
具体使用起来也比较简单
1 | class NewsApi { |
具体可以学习官网 在Flutter中发起HTTP网络请求
Flutter之数据解析
官网也给了反序列化的方法但是感觉比较古老,就跟json一样拿到msg一个个解析,有个更好的方式直接反序列化成对象,后面使用更加快捷
首先需要添加依赖
1 | dependencies: |
具体用法可以参考 https://juejin.im/post/5b5f00e7e51d45190571172f#heading-13