flutter第二章:进阶

上一章讲解了flutter的一些基础控件,这一样讲解一下网络请求,路由等内容。

一,网络请求

1,请求示例

在项目的pubspec.yaml中导入http库

dependencies:
  flutter:
    sdk: flutter
  http: ^0.12.0 //http库
  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2

在body中引入一个HttpDemo,用来请求网络数据并且显示在页面上。

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;//网络请求
import 'dart:convert';//json转换

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: HttpDemo(),//网络请求实现
      ),
      theme: ThemeData(primarySwatch: Colors.lightBlue),
    );
  }
}

HttpDemo的实现部分,一个get请求,请求地址是豆瓣电影排行

class HttpDemo extends StatefulWidget {
  @override
  _HttpDemoState createState() => _HttpDemoState();
}

class _HttpDemoState extends State<HttpDemo> {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    fetchPost(); //请求
  }

  fetchPost() async {
    final response = await http
        .get('https://api.douban.com/v2/movie/top250?start=0&count=10');
    print('statusCode=${response.statusCode}'); //请求状态码
    print('body=${response.body}'); //请求实体
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container();
  }
}

把请求后的状态码和数据打印出来

在这里插入图片描述

开始解析数据,用ListView显示出来,如下效果

在这里插入图片描述

修改HttpDemo代码如下:

class HttpDemo extends StatefulWidget {
  @override
  _HttpDemoState createState() => _HttpDemoState();
}

class _HttpDemoState extends State<HttpDemo> {

  Future<List<MovieRank>> getMovie() async {
    final response = await http
        .get('https://api.douban.com/v2/movie/top250?start=0&count=20');
    if (response.statusCode == 200) {
      //请求成功
      final body = json.decode(response.body);
      List subjects = body['subjects'];
      return subjects.map((item) => MovieRank.fromJson(item)).toList();
    }
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return FutureBuilder(
      future: getMovie(),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(
            child: Text('loading...'),
          );
        }
        return ListView(
          children: snapshot.data.map<Widget>((item) {
            return Card(
              child: Row(
                children: <Widget>[
                  Image.network(
                    item.image,
                    height: 100,
                    width: 50,
                  ),
                  Column(
                    crossAxisAlignment:CrossAxisAlignment.start,
                    children: <Widget>[
                      Text(
                        item.title,
                        style: TextStyle(
                          fontSize: 20.0,
                          color: Colors.black
                        ),
                      ),
                      Text(
                        '年代:${item.year}',
                        style: TextStyle(
                          fontSize: 16.0,
                          color: Colors.grey
                        ),
                      )
                    ],
                  )
                ],
              ),
            );
          }).toList(),
        );
      },
    );
  }
}

class MovieRank {
  final String title; //电影名字
  final String image; //电影图片
  final String year; //年份
  MovieRank(this.title, this.image, this.year);

  MovieRank.fromJson(Map json)
      : this.title = json['title'],
        this.image = json['images']['small'],
        this.year = json['year'];
}

在HttpDemo中使用了FutureBuilder,有关FutureBuilder讲解可以看FutureBuilder

二,路由

路由(Route)在移动开发中通常指页面(Page),这跟web开发中单页应用的Route概念意义是相同的,Route在Android中通常指一个Activity,在iOS中指一个ViewController。所谓路由管理,就是管理页面之间如何跳转,通常也可被称为导航管理。这和原生开发类似,无论是Android还是iOS,导航管理都会维护一个路由栈,路由入栈(push)操作对应打开一个新页面,路由出栈(pop)操作对应页面关闭操作,而路由管理主要是指如何来管理路由栈。

实现页面跳转关键代码,跳转到页面MyPage并且传入值。

  Navigator.push(context,
                MaterialPageRoute(
                    builder: (context) {
                    return MyPage();
                    }));

页面返回

Navigator.pop(context)

MaterialPageRoute 是Material组件库的一个Widget,它可以针对不同平台,实现与平台页面切换动画风格一致的路由切换动画。

MaterialPageRoute 构造函数的各个参数的意义:

MaterialPageRoute({
    WidgetBuilder builder,
    RouteSettings settings,
    bool maintainState = true,
    bool fullscreenDialog = false,
  })
  • builder是一个WidgetBuilder类型的回调函数,它的作用是构建路由页面的具体内容,返回值是一个widget。
  • settings 包含路由的配置信息,如路由名称、是否初始路由(首页)。
  • maintainState:默认情况下,当入栈一个新路由时,原来的路由仍然会被保存在内存中,如果想在路由没用的时候释放其所占用的所有资源,可以设置maintainState为false。
  • fullscreenDialog表示新的路由页面是否是一个全屏的模态对话框,在iOS中,如果fullscreenDialog为true,新页面将会从屏幕底部滑入(而不是水平方向)。

1,简单示例,实现路由切换页面

在这里插入图片描述
在首页放一个按钮,点击按钮跳转到另一个页面,路由跳转默认是有返回按钮的。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: new HomeDemo()

    );
  }
}

class HomeDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('首页'),
      ),
      body: new Center(
        child: new RaisedButton(
          child: new Text('跳转'),
          onPressed: () {
            Navigator.push(
              context,
              new MaterialPageRoute(builder: (context) => new RouteDemo()),
            );
          },
        ),
      ),
    );
  }
}

class RouteDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('路由页'),
      ),
      body: new Center(
        child: new RaisedButton(
          child: new Text('返回'),
          onPressed: () {
           Navigator.pop(context);
          },
        ),
      ),
    );
  }
}

2,路由也可以指定名字

上边示例中在MyApp的MaterialApp中指定路由名称。

 routes: {
       "route_demo":(context)=>RouteDemo(),
  },

把跳转按钮点击事件修改为

 Navigator.pushNamed(context, "route_demo");

这样就可以通过指定路由名称进行跳转

三,动画

1,倒计时动画
在这里插入图片描述

class CountDown extends StatefulWidget {
  @override
  _CountDownState createState() => _CountDownState();
}

class _CountDownState extends State<CountDown>
    with SingleTickerProviderStateMixin {
  AnimationController animationController;
  Animation animation;

  @override
  void initState() {
    super.initState();
    animationController =
        AnimationController(vsync: this, duration: Duration(seconds: 5));
    animation = IntTween(begin: 5, end: 0).animate(
        CurvedAnimation(parent: animationController, curve: Curves.ease));
  }

  @override
  Widget build(BuildContext context) {
    final double textSize = 56.0;
    return Scaffold(
      appBar: AppBar(
        title: Text('倒计时'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            AnimatedBuilder(animation: animationController,
                builder: (BuildContext context, Widget child) {
                  return Text(animation.value.toString(),
                    style: TextStyle(fontSize: textSize),);
                }),
            RaisedButton(
                child: Text("倒计时"),
                onPressed: () {
                  animationController.forward();
                }
            ),
          ],

        ),
      ),
    );
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值