03、Flutter网络请求

Flutter网络请求

包资源

Flutter包类似于Java语言里的jar包,由全球众多开发者共同提供第三方库。

包仓库

所有包(package)都会发布到Dart的包仓库里,在下面网址输入你想使用的包后点击搜索即可。

包仓库地址为:http://pub.dartlangt.org

使用包需要打开pubspec.yaml文件,在dependencies下添加包的名称及版本:

点击Packages get命令来获取工程配置文件中所添加的引用包,或打开命令行窗口执行flutter packages get命令。

打开main.dart文件,导入url_lancher.dart包

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

此时,就可以使用launch方法来打开url地址:

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: '使用第三方包示例',
      home: Scaffold(
        appBar: AppBar(
          title: Text('使用第三方包示例'),
        ),
        body: Center(
          child: new RaisedButton(
            onPressed: (){
              // 指定url并发起请求
              const url = 'https://www.baidu.com';
              launch(url);
            },
          ),
        ),
      ),
    );
  }
}

Http请求

Htt[协议通常用于做前后端的数据交互。Flutter请求网络有两种方法,一种是用Http请求,另一种是用HttpClient请求。

  • Http请求方式

在使用Http方式请求网络时,需要导入http包,如下所示:

导入库:http: ^0.12.0+1
导入包:import 'package:http/http.dart' as http;

下面的示例中发起一个http的get请求,并将返回的结果信息打印到控制台:

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'http请求示例',
      home: new Scaffold(
        appBar: AppBar(
          title: Text('http请求示例'),
        ),
        body: Center(
          child: RaisedButton(
            onPressed: () {
              var url = 'http://httpbin.org/';
              // 向url发送get请求
              http.get(url).then((response) {
                print("状态: ${response.statusCode}");
                print("正文: ${response.body}");
              });
            },
            child: Text('发送http请求'),
          ),
        ),
      ),
    );
  }
}

HttpClient请求方式

在使用HttpClient方式请求网络时,需要导入io及convert包,如下所示:

import 'dart:convert';
import 'dart.io';

请看下面完整示例代码,示例中使用HttpClient请求了一条天气数据,并将返回的结果信息打印到控制台里。

import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:io';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  // 获取天气数据
  void getWeatherData() async {
    try {
      // 实例化HttpClient对象
      HttpClient httpClient = new HttpClient();
      // 发起请求
      HttpClientRequest request = await httpClient.getUrl(
          Uri.parse("http://wthrcdn.etouch.cn/weather_mini?citykey=101070101"));
      // 等待服务器返回数据
      HttpClientResponse response = await request.close();
      // 使用utf8.decoder从response里解析数据
      var result = await response.transform(utf8.decoder).join();
      // 输出响应头
      print(result);
      httpClient.close();
    } catch (e) {
      print("请求失败: $e");
    } finally {
      // 最后处理操作
    }
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'httpClient请求',
      home: Scaffold(
        appBar: AppBar(title: Text('httpClient请求'),),
        body: Center(
          child: RaisedButton(
            child: Text('获取天气数据'),
            onPressed: getWeatherData,
          ),
        ),
      ),
    );
  }
}

Dio请求方式

Dio是一个强大的Dart Http请求库,支持Restful API、Form-Data、拦截器、请求取消、Cookie管理、文件上传/下载、超时、自定义适配器等。

dio: 3.0.0 #latest version

接下来编写一个获取商品列表数据的示例,具体结构如下所示:

main.dart // 主程序
model // 数据库模型
    good_list_model.dart // 商品列表模型
pages // 视图层
    good_list_page.dart // 商品列表页面
service // 服务层    
    http_service.dart // http请求服务
  1. 在main.dart中的body中添加商品列表页面组件GoodListPage。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dio请求',
      home: Scaffold(
        appBar: AppBar(title: Text('Dio请求'),),
        body: GoodListPage(),
      ),
    );
  }
}

2) 打开http_service.dart,添加request方法。

import 'dart:io';
import 'package:dio/dio.dart';
// Dio请求封装
Future request(url, {formData}) async {
  try{
    Response response;
    Dio dio = new Dio();
    dio.options.contentType = ContentType.parse('application/x-www-form-urlencoded') as String;
    // 发起POST请求,传入url及表单数据
    response = await dio.post(url, data: formData);
    if(response.statusCode == 200) {
      return response;
    }else{
      throw Exception('后端接口异常,请求检查代码和服务器运行情况...');
    }
  }catch(e){
    return print('error:::${e.toString()}');
  }
}
  1. 打开good_list_page.dart文件编写商品列表数据模型。(JSON转Model和Model转JSON)
// 商品列表数据模型
class GoodListModel{
  // 状态码
  String code;
  // 状态信息
  String message;
  // 商品列表数据
  List<GoodModel> data;
  // 通过传入json数据转换成数据模型
  GoodListModel.fromJson(Map<String, dynamic> json){
    code = json['code'];
    message = json['message'];
    if(json['data'] != null) {
      data = List<GoodModel>();
      // 循环迭代JSON数据并将每一项数据转换成GoodModel
      json['data'].forEach((v){
        data.add(GoodModel.fromJson(v));
      });
    }
  }
  // 将数据模型转换成json
  Map<String, dynamic> toJson() {
    Map<String, dynamic> data = new Map();
    data['code'] = this.code;
    data['message'] = this.message;
    if(this.data != null) {
      data['data'] = this.data.map((e) => e.toJson()).toList();
    }
    return data;
  }
}
// 商品信息模型
class GoodModel {
  // 商品图片
  String image;
  // 原价
  String oriPrice;
  // 现有价格
  String presentPrice;
  // 商品名称
  String name;
  // 商品id
  String goodsId;
  // 构造方法
  GoodModel(
      this.image, this.oriPrice, this.presentPrice, this.name, this.goodsId);
  // 通过传入json数据转换成数据模型
  GoodModel.fromJson(Map<String, dynamic> json){
    image = json['image'];
    oriPrice = json['oriPrice'];
    presentPrice = json['presentPrice'];
    name = json['name'];
    goodsId = json['goodsId'];
  }
  // 将数据模型转换成json
  Map<String, dynamic> toJson() {
    Map<String, dynamic> data = new Map();
    data['image'] = this.image;
    data['oriPrice'] = this.oriPrice;
    data['presentPrice'] = this.presentPrice;
    data['name'] = this.name;
    data['goodsId'] = this.goodsId;
    return data;
  }
}
  1. 编写商品列表界面,打开good_list_page.dart文件,添加GoodListPage组件,需要继承StatefulWidget有状态组件。
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_dio/model/good_list_model.dart';
import 'package:flutter_dio/service/http_service.dart';
// 商品列表页面
class GoodListPage extends StatefulWidget {
  @override
  _GoodListPageState createState() => new _GoodListPageState();
}
class _GoodListPageState extends State<GoodListPage> {
  // 初始化数据模型
  GoodListModel goodListModel;
  // 滚动控制
  var scrollController = new ScrollController();
  @override
  initState(){
    super.initState();
    // 获取商品数据
    getGoods();
  }
  @override
  Widget build(BuildContext context) {
    // 通过商品列表判断数组长度来判断是否有数据
    if(goodListModel.data.length > 0) {
      return ListView.builder(
        // 列表长度
        itemCount: goodListModel.data.length,
        // 滚动控制器
        controller: scrollController,
        // 列表构造器
        itemBuilder: (context, index){
          return _ListWidget(goodListModel.data, index);
        },
      );
    }else{
      // 商品列表没有数据时返回空容器
      return Container();
    }
  }
  // 获取商品数据
  Future<void> getGoods() async {
    // 请求url
    var url = 'http://127.0.0.1:3000/getDioData';
    // 请求参数,店铺Id
    var formData = {'shopId': '001'};
    // 调用请求方法传入url表单数据
    await request(url, formData:formData).then((value){
      // 返回数据进行json解码
      var data = json.decode(value.toString());
      // 打印数据
      print('商品数据列表Json格式:::' + data.toString());
      // 设置状态刷新数据
      setState(() {
        // 将返回的json数据转换成Model
        goodListModel = GoodListModel.fromJson(data);
      });
    });
  }
  // 商品列表项
  Widget _ListWidget(List<GoodModel> list, int index) {
    return Container(
      padding: EdgeInsets.only(top: 5.0, bottom: 5.0),
      decoration: BoxDecoration(
        color: Colors.white,
        border: Border(
          bottom: BorderSide( 1.0, color: Colors.black12),
        ),
      ),
      // 水平方向布局
      child: Row(
        children: [
          // 返回商品图片
          _goodsImage(list, index),
          SizedBox( 10,),
          // 右侧使用垂直布局
          Column(
            children: [
              _goodsName(list, index),
              _goodsPrice(list, index),
            ],
          ),
        ],
      ),
    );
  }
  // 商品图片
  Widget _goodsImage(List<GoodModel> list, int index) {
    return Container(
       150,
      height: 150,
      child: Image.network(list[index].image, fit: BoxFit.fitWidth,),
    );
  }
  // 商品名称
  Widget _goodsName(List<GoodModel> list, int index) {
    return Container(
      padding: EdgeInsets.all(5.0),
       200,
      child: Text(list[index].name, maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 18),),
    );
  }
  // 商品价格
  Widget _goodsPrice(List<GoodModel> list, int index) {
    return Container(
      margin: EdgeInsets.only(top: 20.0),
       200,
      child: Row(
        children: [
          Text('价格¥${list[index].presentPrice}', style: TextStyle(color: Colors.red),),
          Text('¥${list[index].oriPrice}'),
        ],
      ),
    );
  }
}
原文地址:https://www.cnblogs.com/pengjingya/p/14928341.html