Flutter 用 Dio的 Patch请求完成数据编辑功能

简介: 本篇介绍了详情数据的获取,实体对象的部分修改来展示 Dio的 patch 请求。可以看到,Dio 提供的一系列 Restful 请求的方式基本相同,可以做到更好的封装。

前言

本篇介绍表单更新请求,利用 Patch 请求更新动态数据,需要做得准备工作如下:

  • 拉取后台新的代码,项目地址:后台源码,拉到本地后,在项目目录运行 node seed.js 生成测试数据。
  • 运行后台应用:在项目目录node index.js 即可运行后台接口应用,项目默认接口地址为:http://localhost:3900/api/

整理代码

回顾一下上一篇的代码,发现上一篇的提醒错误代码和业务无关,可以抽离为一个公共的方法,方便后面在其他地方调用,新建一个 utils/dialogs.dart 文件,将错误提示方法移到里面:

import 'package:flutter/material.dart';

class Dialogs {
  static void showInfo(BuildContext context, String info) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text(info),
    ));
  }
}

之前我们在列表是在 initialState 方法里主动刷新请求数据的,实际上 EasyRefresh 本身提供了一个属性firstRefresh来设置首次是否自动刷新,因此我们可以移除之前的主动刷新代码,将 firstRefresh 设置为 true 即可。

编辑页面实现

首先新增一个 dynamic_edit.dart 文件,里面有三个表单和一个按钮,分别对应的是标题、内容和图片链接地址(这里我们暂时不考虑图片上传)。表单利用的是我们之前封装的通用表单组件,可以参考之前的:Flutter 入门与实战(十):封装一个通用的文本输入框。这里在没有请求到数据的时候我们显示“加载中...”,若请求成功则显示实际的表单内容,构建界面的代码如下:

_getFormWidgets() {
  if (_formData == null)
    return Center(
      child: Text('加载中...'),
    );
  return Container(
    child: Column(
      children: [
        FormUtil.textField(
          'title',
          _formData['title']['value'] ?? '',
          controller: _formData['title']['controller'] ?? null,
          hintText: '请输入标题',
          prefixIcon: Icons.title,
          onChanged: _handleTextFieldChanged,
          onClear: _handleClear,
        ),
        FormUtil.textField(
          'content',
          _formData['content']['value'] ?? '',
          controller: _formData['content']['controller'] ?? null,
          hintText: '请输入内容',
          prefixIcon: Icons.content_paste,
          onChanged: _handleTextFieldChanged,
          onClear: _handleClear,
        ),
        FormUtil.textField(
          'imageUrl',
          _formData['imageUrl']['value'] ?? '',
          controller: _formData['imageUrl']['controller'] ?? null,
          hintText: '请输入图片链接',
          prefixIcon: Icons.image,
          onChanged: _handleTextFieldChanged,
          onClear: _handleClear,
        ),
        ButtonUtil.primaryTextButton('保存', () {
          _handleSubmit();
        }, context),
      ],
    ),
  );
}

在列表项的长按弹层中我们增加了一个编辑按钮,点击后跳转到编辑页面,具体参考源码即可。

获取详情数据

在编辑前,我们要通过 id 请求后台数据来填充表单,这里使用之前讲过的 get 请求,方法如下。若请求成功,返回状态码200时,构建表单的_formData数据,也就是表单所需要的数据,同时更新界面。如果请求失败则调用封装的信息提示方法,显示错误信息。

void _getDynamic(String id) async {
    try {
      var response = await DynamicService.get(id);
      if (response.statusCode == 200) {
        dynamicEntity = DynamicEntity.fromJson(response.data);
        setState(() {
          _formData = {
            'title': {
              'value': dynamicEntity.title,
              'controller': TextEditingController(text: dynamicEntity.title),
              'obsecure': false,
            },
            'content': {
              'value': dynamicEntity.content,
              'controller': TextEditingController(text: dynamicEntity.content),
              'obsecure': false,
            },
            'imageUrl': {
              'value': dynamicEntity.imageUrl,
              'controller': TextEditingController(text: dynamicEntity.imageUrl),
              'obsecure': false,
            },
          };
        });
      } else {
        Dialogs.showInfo(this.context, response.statusMessage);
      }
    } on DioError catch (e) {
      Dialogs.showInfo(this.context, e.message);
    } catch (e) {
      Dialogs.showInfo(this.context, e.toString());
    }
  }

提交更新数据

在提交数据前我们需要做校验,这里为了简单起见,只是保证数据不为空即可,后续我们可以校验工具来对各个字段进行准确的校验。校验通过后,从_fromData中提取实际要提交的表单数据。

_handleSubmit() async {
  if ((_formData['title']['value'] as String).trim() == '') {
    Dialogs.showInfo(this.context, '标题不能为空');
    return;
  }

  if ((_formData['content']['value'] as String).trim() == '') {
    Dialogs.showInfo(this.context, '内容不能为空');
    return;
  }

  if ((_formData['imageUrl']['value'] as String).trim() == '') {
    Dialogs.showInfo(this.context, '图片链接不能为空');
    return;
  }

  try {
    Map<String, String> newFormData = {};
    _formData.forEach((key, value) {
      newFormData[key] = value['value'];
    });
    var response = await DynamicService.update(dynamicEntity.id, newFormData);
    if (response.statusCode == 200) {
      Dialogs.showInfo(context, '保存成功');
    } else {
      Dialogs.showInfo(this.context, response.statusMessage);
    }
  } on DioError catch (e) {
    Dialogs.showInfo(this.context, e.message);
  } catch (e) {
    Dialogs.showInfo(this.context, e.toString());
  }
}

实际可以发现,我们的网络请求除了请求方法不同以外,其他代码几乎如出一辙,这也是后面的篇章需要统一封装的原因,要不太多重复代码了,万一哪天改起来会很痛苦。DynamicService.update接收要更新的数据的 id 和要更新的表单数据,实际就是简单调用了 Diopatch 方法。

static Future update(String id, Map<String, dynamic> data) async {
  var result = await Dio().patch(host + 'dynamics/' + id, data: data);

  return result;
}

运行效果

编辑完成后,我们重新刷新数据,可以看到内容和图片都发生了改变(如何保存成功后自动同步列表,我们讲完添加后再一起来解决)。

屏幕录制2021-07-05 下午9.59.35.gif

总结

本篇介绍了详情数据的获取,实体对象的部分修改来展示 Dio的 patch 请求。可以看到,Dio 提供的一系列 Restful 请求的方式基本相同,这样给我们统一封装留下了空间。下一篇我们介绍如何创建数据以及操作成功后如何同步更新后的数据到列表,网络相关代码源码地址为:https://gitee.com/island-coder/flutter-beginner/tree/master/network


欢迎关注个人公众号:岛上码农

相关文章
|
3天前
|
iOS开发 UED
Flutter 动态修改应用图标功能指南
探索Flutter中动态应用图标的实现方法,了解如何为用户提供独特体验,促进用户升级和应用内购买。
100 0
Flutter 动态修改应用图标功能指南
|
3天前
|
移动开发 JavaScript 前端开发
【Uniapp 专栏】Uniapp 与 Flutter 的功能特点对比
【5月更文挑战第15天】Uniapp 和 Flutter 是跨平台开发的热门框架。Uniapp 以其强大的跨平台兼容性和基于 Vue.js 的易学性著称,适合快速开发适用于 iOS、Android 和 H5 的应用。其丰富的组件生态简化了功能集成。然而,在复杂场景下,性能可能不及原生。Flutter 则以其全新渲染引擎实现流畅界面和高度自定义,性能接近原生,但学习成本较高,需处理特定平台适配。适用于高要求的项目。两者各有优势,选择应考虑项目需求、技术储备和开发周期。
【Uniapp 专栏】Uniapp 与 Flutter 的功能特点对比
|
3天前
|
存储 缓存 开发框架
Flutter的网络请求:使用Dart进行HTTP请求的技术详解
【4月更文挑战第26天】了解Flutter网络请求,本文详述使用Dart进行HTTP请求
|
3天前
|
安全 网络安全 开发工具
对象存储oss使用问题之flutter使用http库进行post请求文件上传返回400如何解决
《对象存储OSS操作报错合集》精选了用户在使用阿里云对象存储服务(OSS)过程中出现的各种常见及疑难报错情况,包括但不限于权限问题、上传下载异常、Bucket配置错误、网络连接问题、跨域资源共享(CORS)设定错误、数据一致性问题以及API调用失败等场景。为用户降低故障排查时间,确保OSS服务的稳定运行与高效利用。
47 1
|
8月前
|
存储 缓存 安全
Flutter:类功能索引(全)
本文以表描述形式收录了Flutter中提供的各个类,旨在方便地进行查询相关组件。
198 2
|
3天前
Flutter StatefulWidget传递数据,多级控件传递数据
Flutter StatefulWidget传递数据,多级控件传递数据 在Flutter中,StatefulWidget可以通过构造函数将数据传递给其子控件,这种方式适用于一些简单的场景。但是,当存在多级嵌套控件时,将数据从祖先传递到后代可能会变得困难。在这种情况下,可以使用Flutter提供的InheritedWidget类来传递数据。
|
7月前
|
API 开发者 索引
Flutter笔记:发布一个多功能轮播组件 awesome_carousel
awesome_carousel 模块是一个Flutter轮播图模块。可以实现包括自定义指示器、动画、滚动等等众多功能。能够指定相当多地细节(可以参考 API 部分了解)本文给出 awesome_carousel 模块的两个简单的用法示例。
92 0
|
11月前
|
容器
Flutter的手势识别功能实现GestureDetector
Flutter的手势识别功能实现GestureDetector
Flutter实时动态UI刷新、数据交互
Flutter实时动态UI刷新、数据交互