Flutter 开发 Http dio 网络库的封装以及使用

配置

  • 1、打开项目中 pubspec.yaml 文件

  • 2、找到 dependencies (第三方框架管理)

    在 dependencies 下面添加 dio: ^1.0.0dio: 1.0.0(具体格式:name:^+version),如下图所示

pubspec dependencies

封装

  • http_utils - A HTTP tool to receive data, download and upload files, etc.

Next, the source code is shown as follows:

//
// Created by dyf on 2018/9/3.
// Copyright (c) 2018 dyf.
//

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

export 'package:dio/dio.dart';
export 'dart:io';

// ===============================================
// Response callbacks the http info.
// ===============================================

/// When data is received, it is called.
typedef void OnResponseSuccess(Response response);

/// When the request fails, it is called.
typedef void OnResponseError(DioError error);


/// Defines a HTTP tool to receive data, download and upload files, etc.
class HttpUtils {
  /// Request base url, it can contain sub path, like: "https://www.google.com/api/".
  String baseUrl;

  /// Timeout in seconds for opening url.
  int connectTimeout;

  /// This is not the receiving time limitation, in seconds.
  int receiveTimeout;

  /// Http request headers.
  Map headers;

  /// The request Content-Type. The default value is [ContentType.json].
  /// If you want to encode request body with "application/x-www-form-urlencoded",
  /// you can set `ContentType.parse("application/x-www-form-urlencoded")`, and [Dio]
  /// will automatically encode the request body.
  ContentType contentType;

  /// Cookie manager for http requests。Learn more details about
  /// CookieJar please refer to [cookie_jar](https://github.com/flutterchina/cookie_jar)
  CookieJar cookieJar;

  /// A powerful Http client.
  Dio _dio;

  /// You can cancel a request by using a cancel token.
  CancelToken _cancelToken;

  /// Each Dio instance has a interceptor by which you can intercept requests or responses before they are
  /// handled by `then` or `catchError`. the [interceptor] field
  /// contains a [RequestInterceptor] and a [ResponseInterceptor] instance.
  Interceptor get interceptor => _dio.interceptor;

  /// If the `url` starts with "http(s)", the `baseURL` will be ignored, otherwise,
  /// it will be combined and then resolved with the baseUrl.
  String url = "";

  /// Success response callback.
  OnResponseSuccess _onSuccess;

  /// Failure response callback.
  OnResponseError _onError;

  /// Constructor
  HttpUtils({
    this.baseUrl,
    this.connectTimeout: 0,
    this.receiveTimeout: 0,
    this.headers,
    this.contentType,
    this.cookieJar
  });

  /// Named constructor
  HttpUtils.config({
    String baseUrl,
    int connectTimeout: 0,
    int receiveTimeout: 0,
    Map headers,
    ContentType contentType,
    CookieJar cookieJar
  }) : connectTimeout = 0,
       receiveTimeout = 0 {
    if (baseUrl != null) {
      this.baseUrl = baseUrl;
    }
    if (connectTimeout > 0) {
      this.connectTimeout = connectTimeout;
    }
    if (receiveTimeout > 0) {
      this.receiveTimeout = receiveTimeout;
    }
    if (headers != null) {
      this.headers = headers;
    }
    if (contentType != null) {
      this.contentType = contentType;
    }
    if (cookieJar != null) {
      this.cookieJar = cookieJar;
    }
  }

  void _init() {
    _cancelToken = new CancelToken();
    // Create Dio instance with default [Options].
    _dio = new Dio();
  }

  void _mergeOptions() {
    if (baseUrl != null) {
      _dio.options.baseUrl = baseUrl;
    }
    if (connectTimeout > 0) {
      _dio.options.connectTimeout = 1000 * connectTimeout;
    }
    if (receiveTimeout > 0) {
      _dio.options.receiveTimeout = 1000 * receiveTimeout;
    }
    if (headers != null) {
      _dio.options.headers = headers;
    }
    if (contentType != null) {
      _dio.options.contentType = contentType;
    }
  }

  String _checkPath(String path) {
    if (baseUrl != null && baseUrl.isNotEmpty && path.contains(baseUrl)) {
      url = path;
    } else {
      url = (baseUrl ?? "") + path;
    }
    return url;
  }

  void _checkCookie() {
    if (cookieJar != null) {
      _dio.cookieJar = cookieJar;
    }
  }

  /// Callback to listen the http info.
  void listen(OnResponseSuccess onSuccess, OnResponseError onError) {
    _onSuccess = onSuccess;
    _onError = onError;
  }

  /// Handy method to make http GET request.
  void get(String path, {data}) async {
    try {
      _init();
      _mergeOptions();
      _checkCookie();

      var url = _checkPath(path);
      var response;
      if (data != null) {
        response = await _dio.get(url, data: data, cancelToken: _cancelToken);
      } else {
        response = await _dio.get(url, cancelToken: _cancelToken);
      }

      if (_onSuccess != null) _onSuccess(response);
    } on DioError catch (e) {
      if (_onError != null) _onError(e);
    }
  }

  /// Handy method to make http POST request.
  void post(String path, {data}) async {
    try {
      _init();
      _mergeOptions();
      _checkCookie();

      var url = _checkPath(path);
      var response;
      if (data != null) {
        response = await _dio.post(url, data: data, cancelToken: _cancelToken);
      } else {
        response = await _dio.post(url, cancelToken: _cancelToken);
      }

      if (_onSuccess != null) _onSuccess(response);
    } on DioError catch (e) {
      if (_onError != null) _onError(e);
    }
  }

  /// Handy method to make http PUT request.
  void put(String path, {data}) async {
    try {
      _init();
      _mergeOptions();
      _checkCookie();

      var url = _checkPath(path);
      var response;
      if (data != null) {
        response = await _dio.put(url, data: data, cancelToken: _cancelToken);
      } else {
        response = await _dio.put(url, cancelToken: _cancelToken);
      }

      if (_onSuccess != null) _onSuccess(response);
    } on DioError catch (e) {
      if (_onError != null) _onError(e);
    }
  }

  /// Handy method to make http HEAD request.
  void head(String path, {data}) async {
    try {
      _init();
      _mergeOptions();
      _checkCookie();

      var url = _checkPath(path);

      var response;
      if (data != null) {
        response = await _dio.head(url, data: data, cancelToken: _cancelToken);
      } else {
        response = await _dio.head(url, cancelToken: _cancelToken);
      }

      if (_onSuccess != null) _onSuccess(response);
    } on DioError catch (e) {
      if (_onError != null) _onError(e);
    }
  }

  /// Handy method to make http DELETE request.
  void delete(String path, {data}) async {
    try {
      _init();
      _mergeOptions();
      _checkCookie();

      var url = _checkPath(path);

      var response;
      if (data != null) {
        response = await _dio.delete(url, data: data, cancelToken: _cancelToken);
      } else {
        response = await _dio.delete(url, cancelToken: _cancelToken);
      }

      if (_onSuccess != null) _onSuccess(response);
    } on DioError catch (e) {
      if (_onError != null) _onError(e);
    }
  }

  /// Handy method to make http PATCH request.
  void patch(String path, {data}) async {
    try {
      _init();
      _mergeOptions();
      _checkCookie();

      var url = _checkPath(path);

      var response;
      if (data != null) {
        response = await _dio.patch(url, data: data, cancelToken: _cancelToken);
      } else {
        response = await _dio.patch(url, cancelToken: _cancelToken);
      }

      if (_onSuccess != null) _onSuccess(response);
    } on DioError catch (e) {
      if (_onError != null) _onError(e);
    }
  }

  /// Download the file and save it in local. The default http method is "GET".
  void download(String path, String savePath, {OnDownloadProgress onProgress, data}) async {
    try {
      _init();
      _mergeOptions();
      _checkCookie();

      var url = _checkPath(path);

      var response;
      if (data != null) {
        response = await _dio.download(url, savePath,
            onProgress: onProgress, cancelToken: _cancelToken, data: data);
      } else {
        response = await _dio.download(url, savePath,
            onProgress: onProgress, cancelToken: _cancelToken);
      }

      if (_onSuccess != null) _onSuccess(response);
    } on DioError catch (e) {
      if (_onError != null) _onError(e);
    }
  }

  /// Handy method to make http POST request.
  /// [UploadFileInfo] Describes the info of file to upload,
  /// e.g.: UploadFileInfo(new File("./example/upload.txt"), "upload.txt").
  void upload(String path, Map data) async {
    try {
      _init();
      _mergeOptions();
      _checkCookie();

      var url = _checkPath(path);

      FormData formData = new FormData.from(data);
      var response =
          await _dio.post(url, data: formData, cancelToken: _cancelToken);

      if (_onSuccess != null) _onSuccess(response);
    } on DioError catch (e) {
      if (_onError != null) _onError(e);
    }
  }

  /// Cancel the request.
  void cancel() {
    _cancelToken.cancel();
  }
}

使用示例

  • HttpUtils 示例
class _MyHomePageState extends State {
  int _counter = 0;

  String _data = "";

  void _getTokenData() {
    var baseUrl = "https://etherscan.io";
    var httpUtils = new HttpUtils.config(baseUrl: baseUrl);
    httpUtils.connectTimeout = 10;
    // httpUtils.contentType = ContentType.html;
    // 0x71c7656ec7ab88b098defb751b7401b5f6d8976f
    httpUtils.get("/address/0x71c7656ec7ab88b098defb751b7401b5f6d8976f");
    print("url: ${httpUtils.url}");
    httpUtils.listen((Response response) {
      String data = response.data;
      //print("data: $data");
      setState(() {
        _data = data;
      });
    }, (DioError error) {
      print("e: ${error.message}");
    });
  }

  void _getTokenholdingsData() async {
    String a = "0x71c7656ec7ab88b098defb751b7401b5f6d8976f";
    String data = await EthTokenholdingsDataRequest.init(a).getData();
    if (data != null && data.isNotEmpty) {
      EthTokenholdingsParser.parse(data, a);
    }
  }

  @override
  void initState() {
    super.initState();
    _getTokenData();
    _getTokenholdingsData();
  }

  void _incrementCounter() {
    if (_data.isNotEmpty) {
      EthTokenParser.parse(_data).then((finished){
        if (finished) {
          Navigator.push(context, _createPushRoute());
        }
      });
    } else {
      print("data is empty.");
    }
  }

  MaterialPageRoute _createPushRoute() {
    return MaterialPageRoute(builder: (context) => 
      new EthTokensDisplayView("0x71c7656ec7ab88b098defb751b7401b5f6d8976f")
    );
  }

  @override
  Widget build(BuildContext context) {

    return new Scaffold(
      appBar: new AppConfigurator('UI').createAppBar(
        title: new Text(widget.title, style: new TextStyle(fontSize: 18.0),)
      ),
     
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            new Text(
              'You have pushed the button this many times:',
            ),
            new Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ), 
    );
  }
}
  • dio 示例
//
// Created by dyf on 2018/9/7.
// Copyright (c) 2018 dyf.
//

import 'dart:async';

import 'package:dio/dio.dart';
import 'package:html/parser.dart' as html;

import './HtmlConverter.dart';
import './ExtendedUtility.dart';

class EthTokenholdingsDataRequest {
  String _address;

  EthTokenholdingsDataRequest(String address) {
    _address = address;
  }

  EthTokenholdingsDataRequest.init(String address)
   : this(address);

  int _getCount(String input) {
    return ExtendedString(input).toInt();
  }

  int _getRow(String input) {
    var dom = html.parse(input);
    List tbodyList = dom.getElementsByTagName("tr");
    return tbodyList.length;
  }

  int _getTotalPage(int count, int row) {
    double doub = count / row;
    int page = count ~/ row;
    if (doub > page) {
      page += 1;
    }
    return page;
  }

  String _getUrl(int page) {
    String baseUrl = "https://etherscan.io";
    var a = "&a=" + _address;
    var q = "&q=";
    var p = "&p=$page";
    var f = "&f=";
    var h = "&h=";
    var fav = "&fav=";
    var s = "&sort=total_price_usd";
    var o = "&order=desc";
    var url = baseUrl + "/tokenholdingsHandler.ashx?" + a + q + p + f + h + fav + s + o;
    return url;
  }

  String _convertToHtml(String input) {
    return new HtmlConverter.init(input).convert(isTable: true);
  }

  Future _doDataRequest(int p) async {
    try {
      var dio = new Dio();
      dio.options.connectTimeout = 5*1000;
      var url = _getUrl(p);
      print("url: $url");
      Response response = await dio.get(url); 
      return response;
    } on DioError catch(e) {
      return e;
    }
  }

  Future getData() async {
    var ret = await _doDataRequest(1);
    if (ret is Response) {
      var data = ret.data;
      if (data != null && data is Map && data.isNotEmpty) {  
        var records = data["recordsfound"];
        
        int count = _getCount(records);
        if (count > 0) {
          var tbody = data["layout"];
          int row = _getRow(_convertToHtml(tbody));
          int page = _getTotalPage(count, row);
          
          String allData = await _getOtherData(tbody, page);
          return _convertToHtml(allData);
        }
      }
    } else {
      print("e: ${ret.toString()}");
    }

    return null;
  }

  Future _getOtherData(String baseData, int p) async {
    String retData = baseData; 
  
    for (int i = 2; i < p + 1; i++) {
      var ret = await _doDataRequest(i);
      if (ret is Response) {
        var data = ret.data;
        if (data is Map) {
          var tbody = data["layout"];
          retData += tbody;
        }
      } else {
        print("e: ${ret.toString()}");
      }
    }

    return retData;
  }
}

写的有不好的地方希望大家指出,我会更正,大家有什么看不明白的,也可以在评论里面提问,我会尽力解答。


点赞+关注,第一时间获取技术干货和最新知识点,谢谢你的支持!

最后祝大家生活愉快~

你可能感兴趣的:(Flutter 开发 Http dio 网络库的封装以及使用)