flutter-dio插件获取网络数据

285 阅读4分钟

使用dio插件获取首页网络数据

  1. 安装dio插件:
    • pubspec.yaml文件中,安装方式如下

      image.png

  2. 发送请求获取网络数据
class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    _loadData();

    super.initState();
  }

  // 发送网络请求 获取首页网络数据
  void _loadData() async {
    // 1.准备请求地址
    String path = 'http://xxxx.com/home/index';
    // 2.创建http client
    Dio dio = Dio();
    // 3.发送请求并获取响应
    try {
      Response response = await dio.get(path);
      print(response.data);
    } catch (e) {
      // 4.捕获异常
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      child: const Text(
        '首页',
        style: TextStyle(fontSize: 20.0),
      ),
    );
  }
}

封装网络请求单例类

为什么要封装网络请求单例类

一个类只允许创建一个实例,那这个类就是一个单例类。这种设计模式就叫做单例设计模式,简称单例模式。

  1. 节省资源:
    • 一个Dio实例就可以发起多个http请求,所以工程中可以只需要一个Dio实例
  2. 全局的配置信息
    • 超时时间、baseUrl等等
  3. 全局的请求头信息
    • 访问后端接口时,请求头中都需要传入用户身份和客户端类型信息
  4. 统一的异常处理
    • 用户身份信息过期的处理等等

封装网络请求单例类实现和测试

实现request.dart

// 网络请求单例类
import 'package:dio/dio.dart';

class ZJYRequestManager {
  // 声明dio
  Dio? dio;

  // 1. 私有的静态属性
  static ZJYRequestManager? _instance;

  // 2. 私有的命名构造函数:用于实例化单例类
  ZJYRequestManager._initManager() {
    // 需要在构造函数里面创建Dio实例
    if (dio == null) {
      // 设置全局配置信息
      BaseOptions baseOptions = BaseOptions(
        connectTimeout: 15000,
        receiveTimeout: 5000,
        baseUrl: 'http://xxx.com/',
      );

      dio = Dio(baseOptions);

      // 使用dio拦截器
      dio!.interceptors.add(InterceptorsWrapper(
        onRequest: (
          RequestOptions options,
          RequestInterceptorHandler handler,
        ) {
          // 发送请求前的拦截操作
          // 如果需要在发送请求前补充一些额外的逻辑,代码这里写
          // 设置全局请求头信息
          options.headers = {
            'Authorization': '', // 用户身份信息(登录之后才有)
            'source-client': 'app', // 客户端类型
          };

          return handler.next(options);
        },
        onResponse: (
          Response e,
          ResponseInterceptorHandler handler,
        ) {
          // 接收响应前的拦截操作
          // 如果需要在接收响应前补充一些额外的逻辑,代码这里写(过滤数据)

          return handler.next(e);
        },
        onError: (
          DioError e,
          ErrorInterceptorHandler handler,
        ) {
          // 捕获到异常时的拦截操作
          // 统一的异常处理

          return handler.next(e);
        },
      ));
    }
  }

  // 3. 创建单例对象 并向外界提供单例对象的方法(工厂构造函数)
  factory ZJYRequestManager() {
    // 判断单例对象是否存在 如果不存在 新建  反之 直接返回单例对象
    if (_instance == null) {
      _instance = ZJYRequestManager._initManager();
    }
    return _instance!;
  }
}

测试home.dart

class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    _loadData();

    super.initState();
  }

  // 发送网络请求 获取首页网络数据
  void _loadData() async {
    // 发送请求并获取响应
    try {
      // 设置全局配置信息之后 发送请求
      Response response = await ZJYRequestManager().dio!.get('home/index');
      print(response.data);
    } catch (e) {
      // 4.捕获异常
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      child: const Text(
        '首页',
        style: TextStyle(fontSize: 20.0),
      ),
    );
  }
}

封装处理请求的公共方法

为什么要封装处理请求的公共方法?

  1. 我们在使用dio插件封装单例类时,需要降低单例类和dio插件的耦合度
  2. 而且尽量不要对外暴露单例类内部的Dio实例
  3. 通过封装处理请求的公共方法,可以将单例类和dio插件解耦,而且对外也不会暴露Dio实例

image.png

如何封装处理请求的公共方法?

  1. 使用dio插件提供的request()方法封装处理请求的公共方法
  2. dio插件提供的request()方法是发送请求的底层方法,可以发送任何类型的请求
  3. 通过对request()方法的封装,我们也可以为单例类封装出一个发送任何类型请求的方法

实现

request.dart

...
  // 处理请求的公共方法
  Future<Response> handleRequest(
    String path,
    String method, {
    data,
    Map<String, dynamic>? queryParameters
  }) {
    return _dio!.request(
      path,
      data: data,
      queryParameters: queryParameters,
      options: Options(method: method),
    );
  }

使用

home.dart

...
  // 发送网络请求 获取首页网络数据
  void _loadData() async {
    try {
      // 使用处理请求的公共方法发送请求
      Response response = await XTXRequestManager().handleRequest('home/index', 'GET');
      print(response.data);
    } catch (e) {
      // 4.捕获异常
      print(e);
    }
  }
...

使用网络请求单例类封装首页接口方法

为什么要封装接口方法?

  1. 有些接口可能会被访问多次,比如获取短信验证码的接口
  2. 所以为了能够实现接口复用和统一维护,我们还需要封装对应的接口方法

如何封装接口方法?

home_api.dart

class HomeAPI {
  // 获取首页数据
  static Future<Response> homeFetch() {
    return XTXRequestManager().handleRequest('home/index', 'GET');
  }
}

使用接口方法

home.dart

...
try {
  // 使用首页接口方法 发送请求
  Response response = await HomeAPI.homeFetch();
  print(response.data);
} catch (e) {
  // 4.捕获异常
  print(e);
}
...