Flutter

Flutter 基础Widget

2018-12-04  本文已影响2人  三季人

万事皆 Widget

Widget 是每个 Flutter 应用的基础。每个 Widget 是一部分用户界面上不可变的定义。和其他框架把 View、controller、 Layout 和其他资源分开定义不一样,Flutter 具有一致的、唯一的对象模型: Widget。

一个 Widget 可以定义:

组合大于继承(Composition > inheritance)

Widget 通常通过组合的方式来构建复杂的 UI。例如,常用的 Container Widget 就是由几个分别负责 布局、绘制、布局和计算大小的 Widget 组成。具体来说,Container 由

等widget 组成。如果要自定义 Container 来实现自定义效果,相比使用继承而言,可以使用组合一些简单的 Widget 实现自定义效果。

[图片上传失败...(image-84ef2a-1543882561066)]

基础 Widget

主要文章: widget概述-布局模型

Flutter有一套丰富、强大的基础widget,其中以下是很常用的:

flutter提供了友好的Widget 的查找地址,可以方便的找到自己组要的组件:

Stateful(有状态) 和 Stateless(无状态) widgets

什么是重点?

  • 有些widgets是有状态的, 有些是无状态的

创建一个有状态的widget

  • 要创建一个自定义有状态widget,需创建两个类:StatefulWidget和State

State的状态管理

  • 有多种方法可以管理状态.

一下是常见状态管理的几种方法

如何决定使用哪种管理方法?以下原则可以帮助您决定:

Flutter通信机制 使用平台通道编写平台特定的代码

平台方法调用
平台方法调用主要分四步:

  1. 定义好交互的协议名称以及参数名称(channelName 、methodName、parameter)
  2. 对应平台工程添加对应的平台调用代码
    • 实现MethodChannel.MethodCallHandler接口
    • onMethodCall() 中根据参数做对应处理
  3. 对应平台界面对应位置注册
  4. flutter中调用
    • 创建MethodChannel(channelName)
    • MethodChannel.invoke(methodName)

平台事件调用
平台事件调用和方法调用类似,步骤如下:

  1. 定义好交互的协议名称以及参数名称(eventlName)
  2. 对应平台工程添加对应的平台调用代码
    • 实现EventChannel.StreamHandler接口
    • 在onListen中的EventChannel.EventSink eventSink可以用来发送事件的结果
  3. 对应平台界面对应位置注册
  4. flutter注册事件
    • 创建EventChannel(eventlName)
    • 开始监听eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);

除了上面提到的MethodChannel,你还可以使用BasicMessageChannel,它支持使用自定义消息编解码器进行基本的异步消息传递。 此外,您可以使用专门的BinaryCodecStringCodecJSONMessageCodec类,或创建自己的编解码器。

Flutter 图片

在Flutter中系统为我们提供了可以加载图片的控件Image,Image 控件提供了如下几种用于加载不同方式的图片。

在flutter中Image支持JPEG, PNG, GIF, Animated GIF, WebP, Animated WebP, BMP, 和 WBMP这几种图片格式。
今天我们主要介绍下两种常用的方式,从asset目录和从network获取图片

从asset目录加载图片

1. 新建存放图片的目录
    想要使Image加载asset加载apk内部的图片,首先需要在项目中建立放置图片的目录(名称随意,不要中文就好)
我们在lib目录的同级目录建立images文件夹,并在里面放置了一个cover.jpg的图片

2. 更细配置文件pubspec.yaml
    在flutter节点下新增 文件声明 ,如下所示
    flutter:
    assets:
     - images/cover.jpg
    
3. 加载目录中的图片文件
    new Image.asset("images/helloflutter.png")

从network获取图片

基本上和上面asset的参数相同,只不过从网络获取的方式可以传入请求头。

但是,从我网络获取图片展示的调用方式就比从asset读取显示方便的多,只需要一行代码就可以搞定
把Scaffold body的参数写为:

new Image.network("http://pic1.win4000.com/wallpaper/2017-10-25/59f083092ed4f.jpg")

Flutter 网络

注:本篇文档官方使用的是用dart io中的HttpClient发起的请求,但HttpClient本身功能较弱,很多常用功能都不支持。我们建议您使用dio 来发起网络请求,它是一个强大易用的dart http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载……详情请查看github dio

处理异步

注意,HTTP API 在返回值中使用了Dart Futures。 我们建议使用async/await语法来调用API。

网络调用通常遵循如下步骤:

get() async {
  var httpClient = new HttpClient();
  var uri = new Uri.http(
      'example.com', '/path1/path2', {'param1': '42', 'param2': 'foo'});
  var request = await httpClient.getUrl(uri);
  var response = await request.close();
  var responseBody = await response.transform(UTF8.decoder).join();
}

Flutter给我们提供了第三发库的支持,同样的下面三个操作

var url = "http://example.com/whatsit/create";
http.post(url, body: {"name": "doodle", "color": "blue"})
    .then((response) {
  print("Response status: ${response.statusCode}");
  print("Response body: ${response.body}");
});

官网还退出了一个网络第三方库 github dio

Dio dio = new Dio();

  _loadDataByDio() async {
    try {
      Response response = await dio.get("https://news-at.zhihu.com/api/4/news/latest");
      if (response.statusCode == HttpStatus.ok) {
        _result = response.data.toString();
      } else {
        _result = 'error code : ${response.statusCode}';
      }
    } catch (exception) {
      print('exc:$exception');
      _result = '网络异常';
    }

    setState(() {});
  }

Flutter路由

静态路由

在Flutter中有着两种路由跳转的方式,一种是静态路由,在创建时就已经明确知道了要跳转的页面和值。另一种是动态路由,跳转传入的目标地址和要传入的值都可以是动态的。

OK,还是先来介绍下静态路由

从我们开始学习Flutter到现在,相信大家看到最多的肯定是下面的代码

void main() {
  runApp(new MaterialApp(
    home: new MyApp(),
    routes: <String, WidgetBuilder>{
      '/page2': (BuildContext context) => new Page2("requestString"),
    },
  ));
}

routes: const {}

routes需要传入类型的Map,第一个参数是目标路由的名称,第二个参数就是你要跳转的页面。

这种定义路由并使用的方式非常的简单,但是大家肯定会发现一个问题,就是如果我需要传递给第二个页面的数据不是已知的话我就无法使用这种方式,因为我们无法动态改变上面定义的值。

所以,我们就需要了解下Flutter中的动态路由了。

动态路由

在Navigator中还有一个方法是push()方法,需要传入一个Route对象,在Flutter中我们可以使用PageRouteBuilder来构建这个Route对象。

Navigator.of(context).push(new PageRouteBuilder(
                        pageBuilder: (BuildContext context,
                            Animation<double> animation,
                            Animation<double> secondaryAnimation) {
                          return new Page2("some attrs you like ");

                        }))

这样的话,我们就可以把用户操作与交互的数据传递给下个页面。

页面出栈

在Flutter中我们可以使用Navigator.of(context).pop()进行出栈操作,但是值得注意的时如果页面上有Dialog、BottomSheet、popMenu类似的Widget使用pop()方法会优先进行这些Widget的关闭操作。

处理出栈页面返回值

在前面我们介绍到Navigator.of(context).pop()可以使得页面出栈,当然这个pop方法也是可以传值的,只用Navigator.of(context).pop(attrs)就可以传入自己想要返回的值

Future future = Navigator.of(context).pushNamed("/pageB");
            future.then((value) {
              showDialog(
                  context: context,
                  child: new AlertDialog(
                    title: new Text(value),
                  ));
            }

小结

Flutter插件

官网提供了很多好用的插件,插件地址

  1. flutter_image
    • 使用NetworkImageWithRetry 代替Image.network 加载网络图片可获得重试能力。
  2. barcode_scan
    • 一个可以扫描二维码和条形码的flutter插件。
  3. intl
    • 该插件提供国际化和本地化设施,包括消息翻译,复数和性别,日期/数字格式和解析以及双向文本。
  4. location
    • 这个插件 能够处理Android和iOS设备的位置。它还提供位置更改时的回调。

等等。。。其他科自行搜索使用。
如果你想开发一个新的插件可以参考开发Packages和插件

项目地址 FlutterDemo

参考

上一篇 下一篇

猜你喜欢

热点阅读