Flutter- 网络请求

前言

FlutterGoogle开源的构建用户界面(UI)工具包,帮助开发者通过一套代码库高效构建多平台精美应用,支持移动、Web、桌面和嵌入式平台。Flutter 开源、免费,拥有宽松的开源协议,适合商业项目。目前,Flutter已推出稳定的2.0版本。也是目前最火的跨平台开发工具之一

header-illustration.png

Dart支持的API请求

之前在Dart语言的学习中,我们直接可以很方便的使用Dart支持的网络请求,在Flutter中也一样,直接这样就可以获取数据源并将其进行展示

  readData() async {
    HttpClientResponse response = await getBaiduData();
    String res = await response.transform(utf8.decoder).join();
    setState(() {
      data = res;
    });
  }

  getBaiduData() async {
    HttpClient client = HttpClient();
    var request = await client.getUrl(Uri.http("www.baidu.com", ""));
    var response = await request.close();
    return response;
  }

Http库

Http库也是我们常用的网络请求框架

添加依赖

http: ^0.12.2

https://github.com/dart-lang/http

数据请求与展示

class HomePageStates extends State
    with SingleTickerProviderStateMixin {
  String data = "";
  bool isShowLoading = false;

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

  getData() async {
    setState(() {
      isShowLoading = true;
    });
     var http = Client();
     Response response = await http.get("https://jsonplaceholder.typicode.com/todos/1");
     setState(() {
       data = response.body;
       isShowLoading = false;
     });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Home'),
          centerTitle: true,
        ),
        body: Stack(
          children: [
            Container(
              alignment: Alignment.center,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text('$data'),
                  Ink(
                    decoration: BoxDecoration(
                        color: Colors.green,
                        borderRadius: BorderRadius.circular(20)),
                    child: InkWell(
                      borderRadius: BorderRadius.circular(20),
                      onTap: () {
                        getData();
                      },
                      splashColor: Colors.white,
                      child: Container(
                        width: 100,
                        height: 40,
                        alignment: Alignment.center,
                        child: Text(
                          'Get',
                          style: TextStyle(color: Colors.white),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
            Visibility(
              visible: isShowLoading,
                child: Container(
              alignment: Alignment.center,
              child: Container(
                width: double.maxFinite,
                height: double.maxFinite,
                child: Center(
                  child: SizedBox(
                    height: 40,
                    width: 40,
                    child: CircularProgressIndicator(
                      strokeWidth: 2,
                      valueColor: AlwaysStoppedAnimation(Colors.blue),
                    ),
                  ),
                ),
              ),
            ))
          ],
        ));
  }
}
http.png

dio

dio库是一个更强大的网络请求框架,支持更多的网络请求设置,拦截器,超时,Cookie,文传等各种设置

https://github.com/flutterchina/dio

添加依赖

dio: ^4.0.1

发起一个简单的请求

  getData() async {
    setState(() {
      isShowLoading = true;
    });

    var dio = Dio();
    var response =
    await dio.get("https://jsonplaceholder.typicode.com/todos/1");
    data = response.data.toString();
    setState(() {
      data = response.data.toString();
      isShowLoading = false;
    });
  }
dio.png

添加一个异常处理

当访问出现异常时,比如资源访问失败,访问超时等

这里由于使用了await 的同步调用,所以需要使用try catch进行异常捕获,当api调用失败时会返回DioError里面封装了错误状态码,错误信息,以及错误类型DioErrorType 用于做判断

enum DioErrorType {
  /// It occurs when url is opened timeout.
  connectTimeout,

  /// It occurs when url is sent timeout.
  sendTimeout,

  ///It occurs when receiving timeout.
  receiveTimeout,

  /// When the server response, but with a incorrect status, such as 404, 503...
  response,

  /// When the request is cancelled, dio will throw a error with this type.
  cancel,

  /// Default error type, Some other Error. In this case, you can
  /// use the DioError.error if it is not null.
  other,
}

这里我使用错误的链接访问

  getData() async {
    setState(() {
      isShowLoading = true;
    });

    try {
      var dio = Dio();
      var response =
          await dio.get("https://jsonplaceholder.typicode.com/todos/1test");
      data = response.data.toString();
    } on DioError catch (e) {
      data =
          "error ${e.type}---${e.response?.statusCode}---${e.response?.statusMessage}";
    } catch (e) {
      //other exception
      data = "other error ${e.toString()}";
    } finally {
      setState(() {
        isShowLoading = false;
      });
    }
  }
error.png

访问超时处理

某些时候当服务不稳定时,会导致请求时间过长,可以设置api的请求超时时间,这里为了测试我们设置1毫秒的超时时间

var dio = Dio(BaseOptions(receiveTimeout: 1,connectTimeout: 1,sendTimeout: 1));
timeout.png

添加拦截器

拦截器是API请求的很重要一部分,我们可以全局拦截发出去的请求数据比如为其添加特殊的Header,或者可以拦截返回的数据信息用来做一些公共处理或者打印日志

添加库提供的日志拦截器,方便我们进行请求调试

var dio = Dio(BaseOptions(receiveTimeout: 10000,connectTimeout: 10000,sendTimeout: 10000)).interceptors.add(LogInterceptor());

也可以自定义拦截器,将请求的额链接替换到https://jsonplaceholder.typicode.com/todos/2

dio.interceptors.add(InterceptorsWrapper(onRequest: (options,handler){
    options.headers['from'] = 'Mike_Test';
    options.path = "https://jsonplaceholder.typicode.com/todos/2";
    handler.next(options);
  }));

数据转换

通常情况下我们会将API返回的Jason数据转换为我们的实体类,这样会方便我们获取其中的字段用于设置和使用

var maps = json.decode("{\"id\":\"2\"}");
var model = ResponseModel(maps["id"]);
print(model.id);

也可以直接安装插件JsonToDart去创建对应的实体类,这样也避免手动写字符串的风险

https://plugins.jetbrains.com/plugin/12562-jsontodart-json-to-dart-

/// id : "2"

class ResponseModel {
  ResponseModel({
    required String id,}){
    _id = id;
  }

  ResponseModel.fromJson(dynamic json) {
    _id = json['id'];
  }
  String _id ="";

  String get id => _id;

  Map toJson() {
    final map = {};
    map['id'] = _id;
    return map;
  }

}
var model = ResponseModel.fromJson(json.decode("{\"id\":\"2\"}"));
print('${model.id}');

欢迎关注Mike的

Android 知识整理

你可能感兴趣的:(Flutter- 网络请求)