[Flutter-31] http_request 网络请求

http_request

  • HttpClient: 是dart自带的请求类、在io包中
  • http库:http库是Dart官方提供的另外一种网络请求类, 但需要手动添加依赖pubspec
  • dio库:是flutter比较受欢迎的一个第三方库,需要手动添加依赖pubspec

1. HttpClient

/* HttpClient
是dart自带的请求类、在io包中
实现了基本的网络请求相关的操作。

1. 创建client
2. 构造url
3. 发起请求、等待请求、同时也可以配置请求header、body
4. 关闭请求、等待响应
5. 解析返回的内容

从下面可以看出来HttpClient 虽然可以发送正常的网络请求、但是会暴露更多细节:
> 需要主动关闭request.close
> 拿到数据需要手动的进行字符串解码

So. 在开发中我们一般使用一些库来完成。

*/
  • http_client.dart
    • 需要主动关闭request.close
    • 拿到数据需要手动的进行字符串解码
import 'dart:convert';
import 'dart:io';

void requestNetworking() async {
  // 1. 创建httpclient
  final httpClient = HttpClient();

  // 2.构建url
  final url = Uri.parse('http://123.207.32.32:8000/api/v1/recommend');

  // 3. 构建请求
  final request = await httpClient.getUrl(url);

  // 4. 发送请求、必须先关闭request
  final response = await request.close();
  if (response.statusCode == HttpStatus.ok) {
    final result = await response.transform(utf8.decoder).join();
    print('响应成功: $result');
  } else {
    print('!ok: ${response.statusCode}');
  }
}

2. http库

/* http库
http库是Dart官方提供的另外一种网络请求类、相比于HttpClient, 易用性能提升了不少
但是没有默认集成到Dart SDK中、需要手动在依赖pubspec中手动添加 如http: ^0.12.0+2

https://pub.flutter-io.cn/packages/http/versions 

http:
相比于HttpClient: 
- 不需要手动关闭request.close
- 不需要手动去解析字符串解码

*/
import 'dart:io';
import 'package:http/http.dart' as http;

void httpNetworking() async {
  // 1. 创建client
  final client = http.Client();

  // 2. 构建url
  final url = Uri.parse('http://123.207.32.32:8000/api/v1/recommend');

  // 3. 发送请求
  final response = await client.get(url);

  // 4. 获取结果
  if (response.statusCode == HttpStatus.ok) {
    print('http-response: ${response.body}');
  } else {
    print('http-!ok: ${response.statusCode}');
  }
}

3. dio 库

  • 结果直接解析出中文
  • 不需要手动关闭request
  • 不需要手动解码结果字符串
  • 使用到额外的功能很简单,比如拦截器、超时设置、取消请求、文件下载/上传等。
/* dio 

官网提供的HttpClient & http 都可以正常发送网络请求、但是对于现代的应用程序开发来说
我们通常需要做很多操作:如拦截器、取消请求、文件上传/下载、超时设置等等

我们可以使用一个flutter第三方库dio

- dio是一个强大的Dart Http请求

*/
import 'dart:io';
import 'package:dio/dio.dart';

void dioNetworking() async {
  // 1. 创建dio 请求对象
  final dio = Dio();

  // 2. 发送网络请求
  final response = await dio.get('http://123.207.32.32:8000/api/v1/recommend');

  // 3. 获取返回结果
  if (response.statusCode == HttpStatus.ok) {
    print('success-dio: ${response.data} \n$response');
  } else {
    print('failure-dio: ${response.statusCode}');
  }
}

4. dio库封装

  • http_config.dart
class HTTPConfig {
  static const baseURL = "https://httpbin.org";
  static const timeout = 5000;
}

  • http_request.dart
import 'package:dio/dio.dart';
import 'package:flutter_networking/dio/http_config.dart';

class HTTPRequest {
  // 基本的options,比如超时时间、基本的url
  static final BaseOptions baseOptions = BaseOptions(
    baseUrl: HTTPConfig.baseURL,
    connectTimeout: HTTPConfig.timeout,
    headers: {},
  );

  static final Dio dio = Dio(baseOptions);

  static Future<T> request<T>(
    String url, {
    String method = 'get',
    Map<String, dynamic>? params,
    Interceptor? inter,
  }) async {
    // 1. 请求的单独配置, 比如请求类型type:
    final options = Options(method: method);

    // 2. 添加第一个拦截器
    Interceptor interceptor = InterceptorsWrapper(
      onRequest: (options, handler) {
        // 2.1: 在进行任何网络请求的时候、可以添加一个loading展示

        // 2.2: 很多页面的访问必须要求携带token、那么就可以在这里判断是否有token

        // 2.3: 对参数进行一些处理、比如系列化处理等
        // flutter: ========> 拦截了请求request: https://httpbin.org/post?name=bmw&age=4, handler:Instance of 'RequestInterceptorHandler'
        print('========> 拦截了请求request: ${options.uri}, handler:$handler');
        return handler.next(options);
      },
      onResponse: (response, handler) {
        print('\n========>拦截了响应response: $response, handler:$handler');
        return handler.next(response);
      },
      onError: (error, handler) {
        print('\n=========>拦截了错误error: $error, handler: $handler');
        return handler.next(error);
      },
    );

    List<Interceptor> inters = [interceptor];
    if (inter != null) {
      inters.add(inter);
    }
    dio.interceptors.addAll(inters);
    print('list: ${inters.length}');

    // 3. 发送网络请求
    try {
      Response response =
          await dio.request<T>(url, queryParameters: params, options: options);
      return response.data;
    } on DioError catch (e) {
      return Future.error(e);
    }
  }
}

5. http_request 使用

import 'package:flutter/material.dart';
import 'package:flutter_networking/dio/http_request.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Networking'),
        ),
        body: Content(),
      ),
    );
  }
}

class Content extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 1. HttpClient request
    // requestNetworking();

    // 2. http request
    // httpNetworking();

    // 3. dio request
    // dioNetworking();

    // 4. dio 封装使用
    // HTTPRequest.request('https://httpbin.org/get',
    //     params: {"name": "bmw", 'age': '4'}).then((response) {
    //   print('dio-封装使用: data: ${response.data}, \nresponse: $response');
    // });

    return Container(
      alignment: Alignment(0.9, 0.95),
      child: FloatingActionButton(
        child: Text('Float'),
        onPressed: () => loadData(),
      ),
    );
  }

  void loadData() async {
    await HTTPRequest.request('/post',
        method: 'post', params: {"name": "bmw", 'age': '4'}).then((response) {
      print('dio-封装使用: response: $response');
    });
  }
}

/* 
response: {
  args: {
    age: 4,
    name: bmw
  },
  headers: {
    Accept-Encoding: gzip,
    Content-Length: 0,
    Host: httpbin.org,
    User-Agent: Dart/2.13(dart: io),
    X-Amzn-Trace-Id: Root=1-61010d4a-7e79c42f56f8d1467074df5e
  },
  origin: 180.168.144.10,
  url: https: //httpbin.org/get?name=bmw&age=4
}
*/

6. 封装的缺陷?

  • dio对象 会累加拦截、需要dio对象设置单例最好。
posted @ 2021-07-28 17:03  comefromchina  阅读(448)  评论(0)    收藏  举报
点击右上角即可分享
微信分享提示