Flutter 入門與實戰(二十四):使用 Dio的 Patch請求完成詳情編輯

前言

這是 Dio 網絡請求的第三篇,咱們將從淺到深完成 Dio 的學習,前面兩篇以下:node

本篇介紹表單更新請求,利用 Patch 請求更新動態數據,須要作得準備工做以下:git

  • 拉取後臺新的代碼,項目地址:後臺源碼,拉到本地後,在項目目錄運行 node seed.js 生成測試數據。
  • 運行後臺應用:在項目目錄node index.js 便可運行後臺接口應用,項目默認接口地址爲:http://localhost:3900/api/

整理代碼

回顧一下上一篇的代碼,發現上一篇的提醒錯誤代碼和業務無關,能夠抽離爲一個公共的方法,方便後面在其餘地方調用,新建一個 utils/dialogs.dart 文件,將錯誤提示方法移到裏面:express

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 便可。api

編輯頁面實現

首先新增一個 dynamic_edit.dart 文件,裏面有三個表單和一個按鈕,分別對應的是標題、內容和圖片連接地址(這裏咱們暫時不考慮圖片上傳)。表單利用的是咱們以前封裝的通用表單組件,能夠參考以前的:Flutter 入門與實戰(十):封裝一個通用的文本輸入框。這裏在沒有請求到數據的時候咱們顯示「加載中...」,若請求成功則顯示實際的表單內容,構建界面的代碼以下:markdown

_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數據,也就是表單所須要的數據,同時更新界面。若是請求失敗則調用封裝的信息提示方法,顯示錯誤信息。async

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 方法。oop

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

  return result;
}
複製代碼

運行效果

編輯完成後,咱們從新刷新數據,能夠看到內容和圖片都發生了改變(如何保存成功後自動同步列表,咱們講完添加後再一塊兒來解決)。post

屏幕錄製2021-07-05 下午9.59.35.gif

(錄屏有點尷尬,粘貼圖片連接半天沒粘貼上😹)

總結

本篇介紹了詳情數據的獲取,實體對象的部分修改來展現 Dio的 patch 請求。能夠看到,Dio 提供的一系列 Restful 請求的方式基本相同,這樣給咱們統一封裝留下了空間。下一篇咱們介紹如何建立數據以及操做成功後如何同步更新後的數據到列表,網絡相關代碼源碼地址爲:gitee.com/island-code…

相關文章
相關標籤/搜索