Flutter 网络请求框架封装详解

yizhihongxing

Flutter 网络请求框架封装详解

网络请求是移动应用中常用的功能,Flutter提供了丰富的网络请求支持和第三方库,如http、dio等。为了简化开发流程,最好将网络请求进行封装。

封装思路

封装网络请求的主要思路是将网络请求的参数进行封装,提高代码复用率和可读性。一般封装网络请求都会包含以下几个步骤:

  1. 封装请求参数和请求路径
  2. 封装请求头
  3. 封装请求体
  4. 封装响应数据处理
  5. 封装异常处理

在封装网络请求时,我们可以使用 Flutter 或第三方库提供的网络请求 API。下面介绍如何使用 dio 封装网络请求。

使用dio封装网络请求

dio 是一个强大的 Darts/Flutter Http 客户端,支持 Restful API、FormData、拦截器、请求取消、Cookie 管理、文件上传/download、超时等功能。在使用 dio 之前,需要在项目的 pubspec.yaml 文件中引入 dio 包。

dependencies:
  dio: ^4.0.0

对于一个网络请求工具类而言,一般需要满足以下几个要求:

  • 代码需要易于维护和扩展
  • 方便我们自定义请求头和拦截器
  • 方便我们统一处理网络请求的异常
  • 支持多种请求方法,如 GET、POST 等
  • 支持请求参数和请求体的封装
  • 支持请求的超时设置
  • 支持文件上传和下载

下面是一个利用 dio 封装网络请求的示例代码,供参考:

import 'package:dio/dio.dart';

class HttpUtil {
  static Dio _dio =
      Dio(BaseOptions(baseUrl: "https://www.xxxx.com", connectTimeout: 5000));

  static Future<dynamic> get(String url,
      {Map<String, dynamic>? queryParameters,
      Options? options}) async {
    Response<dynamic> response;

    try {
      response = await _dio.get(url,
          queryParameters: queryParameters, options: options);
    } on DioError catch (e) {
      _handleError(e);
    }

    return response;
  }

  static Future<dynamic> post(String url,
      {Map<String, dynamic>? queryParameters,
      dynamic data,
      Options? options}) async {
    Response<dynamic> response;

    try {
      response = await _dio.post(url,
          queryParameters: queryParameters, data: data, options: options);
    } on DioError catch (e) {
      _handleError(e);
    }

    return response;
  }

  static void _handleError(DioError e) {
    switch (e.type) {
      case DioErrorType.cancel:
        print("请求已被取消");
        break;
      case DioErrorType.connectTimeout:
        print("连接超时");
        break;
      case DioErrorType.sendTimeout:
        print("请求超时");
        break;
      case DioErrorType.receiveTimeout:
        print("响应超时");
        break;
      case DioErrorType.response:
        print("HTTP 响应异常");
        break;
      case DioErrorType.other:
        print("其它异常");
        break;
      default:
        print("网络异常");
    }
  }
}

在这个示例中,我们利用了 dio 的 BaseOptions 控制超时时间,也使用了 DioError 类型来处理请求异常。同时也支持了 Get 和 Post 等请求方式,支持传入请求参数 Map 和数据体。

示范应用示例

接下来我们将提供两个在 Flutter 中使用网络请求的示范代码示例。

示例1:异步请求天气API

在这个示例中,我们将创建一个简单的天气 API 请求的程序。在这个示例中,我们使用了 http 包和 JSON 解析器 convert 包来获取环球时报的天气 API。

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

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

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _data = "";

  Future<String> _getWeather() async {
    var url = Uri.parse(
        'http://weatherapi.market.xiaomi.com/wtr-v2/weather?cityId=101020100');
    var response = await http.get(url);
    Map<String, dynamic> weatherMap = json.decode(response.body);
    return weatherMap.toString();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Weather API'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              String data = await _getWeather();
              setState(() {
                _data = data;
              });
            },
            child: const Text('Get Weather'),
          ),
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个 MyApp 组件,它有一个有名的 _getWeather() 方法,用来获取 API 返回的天气数据。然后在页面中创建了一个包含 “Get Weather” 文字的 ElevatedButton,用来触发事件,进而刷新页面。

在方法中,我们定义了一个名字为 url 的变量,接着把这个变量转换成 Uri 对象。然后我们使用 HTTP 包中的 http.get 方法请求 API,并且使用 JSON 包解析返回的结果。最后这个方法会输出三天内的天气条件和气温。

示例2:待完成任务列表的更新任务

在这个示例中,我们将创建一个任务列表,用户可以添加任务并将任务标记为已完成。这个任务列表通过 HTTP 请求和 JSON API 来支持在多个设备上同步任务列表。

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

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

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<String> tasks = [];

  Future _getTasks() async {
    var url = Uri.parse('https://api.example.com/tasks');
    var response = await http.get(url);

    Map<String, dynamic> data = json.decode(response.body);

    List<String> newTasks = [];

    for (var taskJson in data['tasks']) {
      newTasks.add(taskJson['title']);
    }

    setState(() {
      tasks = newTasks;
    });
  }

  Future _addTask(String task) async {
    var url = Uri.parse('https://api.example.com/task');

    await http.post(url, body: {'title': task});

    await _getTasks();
  }

  Future _toggleTask(String task) async {
    var url = Uri.parse('https://api.example.com/task/$task');
    var response = await http.put(url);

    await _getTasks();
  }

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

    _getTasks();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Task List'),
        ),
        body: Column(
          children: [
            Expanded(
              child: ListView.builder(
                itemCount: tasks.length,
                itemBuilder: (context, index) {
                  var task = tasks[index];

                  return ListTile(
                    title: Text(task),
                    trailing: Checkbox(
                      value: false,
                      onChanged: (bool? value) {
                        _toggleTask(task);
                      },
                    ),
                  );
                },
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(16.0),
              child: TextField(
                decoration: InputDecoration(hintText: 'Add a task'),
                onSubmitted: (text) {
                  _addTask(text);
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个 MyApp 组件,它包含了一个包含数据抽象的 tasks 列表属性,它使用 HTTP 包和JSON解析器 convert 包来获取环球任务。

在页面中,我们创建了一个任务列表视图,用 ListTile 表示每个任务。点击每项任务右侧的 Checkbox 可以加入或取消完成状态。在最底部的文本框中输入新任务,按下回车键可以添加新任务。

当其中一个列表项被点击时,它将在底层调用 _toggleTask 方法。这个方法通过 HTTP PUT 请求把任务标记为已完成,并调用了 _getTasks 拉取最新的任务数据。在添加新任务时,我们将在底部文本输入框上启动方法,该方法将使用 POST 请求将新任务提交到 API,然后在在底层调用 _getTasks 方法拉取最新的任务数据。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Flutter 网络请求框架封装详解 - Python技术站

(0)
上一篇 2023年6月25日
下一篇 2023年6月25日

相关文章

  • java中object转string

    以下是详细讲解“Java中Object转String的完整攻略,过程中至少包含两条示例说明”的标准Markdown格式文本: Java中Object转String的方法 在Java编程中,我们经常需要将Object类型的数据转换为String类型。以下是两种常用的方法: 1. 使用toString()方法 Java中的Object类有一个toString()…

    other 2023年5月10日
    00
  • bootstrap字体颜色设置菜鸟

    Bootstrap字体颜色设置 在Bootstrap中,可以使用预定义的类来设置字体颜色。本文将介绍如何使用Bootstrap设置字体颜色,并提供两个示例说明。 基本语法 以下是常用的Bootstrap字体颜色类: text-primary:设置字体颜色为主色调。 text-secondary:设置字体颜色为次要色调。 text-success:设置字体颜色…

    other 2023年5月7日
    00
  • mybatis批量删除多态sql 构建in语句

    Mybatis批量删除多态SQL:构建IN语句 在进行批量删除操作时,使用IN语句可以大大减少SQL语句的编写时间和复杂度。本文将介绍使用Mybatis构建IN语句进行批量删除的方法。 构建实体类 我们假设需要删除的实体类名为User,它的主键ID为id。则我们需要在实体类中添加一个名为ids的属性,用于承载将要被删除的ID集合。 public class …

    其他 2023年3月28日
    00
  • rust的package,crate,module示例解析

    Rust的Package、Crate和Module示例解析 在Rust中,有几个重要的概念需要理解,包括Package、Crate和Module。下面将详细解释它们之间的关系和示例。 Package 一个Rust项目通常由一个或多个包组成。一个包是一个包含一个或多个Crate的目录,它包含一个Cargo.toml文件,用于描述项目的元数据和依赖关系。 以下是…

    other 2023年10月13日
    00
  • Maya怎么制作三维立体镂空样式的垃圾桶?

    制作三维立体镂空样式的垃圾桶需要用到Maya软件。下面是具体的制作过程: 步骤一:准备工作 首先打开Maya软件,新建一个文件,选择合适的场景单位,并设置视图为透视或前视图。 步骤二:创建基础模型 首先,我们需要创建一个基本的垃圾桶模型,可以通过创建圆柱体来实现。在Maya的主工具栏中,选择“Create” > “Polygon Primitives”…

    other 2023年6月27日
    00
  • flash cs3总是提示1119访问未定义的属性怎么办?

    解决“flash cs3总是提示1119访问未定义的属性”问题 问题背景 在使用 Flash CS3 进行开发过程中,你可能会遇到一个常见的错误提示:1119 访问未定义的属性。这个错误通常表示你正在尝试访问一个在当前上下文中未定义的属性。这可能是因为你的代码中存在拼写错误、错误的路径引用或者未正确定义属性等问题。在接下来的攻略中,我将为你提供一些解决此问题…

    other 2023年6月28日
    00
  • Java springboot探究配置文件优先级

    为了讲解Java Spring Boot探究配置文件优先级,我们需要以下知识点:Spring Boot应用程序的配置文件、Spring Boot应用程序的启动过程、配置文件优先级、不同配置文件的语法。 Spring Boot应用程序的配置文件 Spring Boot中的应用程序可以使用两种类型的配置文件:.properties和.yaml/.yml文件。.p…

    other 2023年6月25日
    00
  • CentOS 6.3 Rsync客户端与Win2003 cwRsyncServer服务端实现数据同步

    下面我将详细讲解“CentOS 6.3 Rsync客户端与Win2003 cwRsyncServer服务端实现数据同步”的完整攻略,具体步骤如下: 确认准备工作 首先要确认准备工作是否齐备,以下是需要准备的内容: CentOS 6.3系统及cwRsync客户端 Win2003系统及cwRsyncServer服务端 确认两台机器之间网络通畅 在Win2003上…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部