Flutter學習(7)——網路請求框架Dio簡單使用

one發表於2021-08-09

原文地址: Flutter學習(7)——網路請求框架Dio簡單使用 | Stars-One的雜貨小窩

之前的Flutter學習系列都是在個人部落格上釋出的,感興趣可以去看看,就不搬過來了

網路請求一般APP都是需要的,在Flutter中,目前比較流行的網路請求框架是Dio,是Flutter中文網推出的,也算是國人開發的?

本文主要是講解如何簡單使用Dio的get請求來獲取資料,並使用Flutter中的listview進行展示

關於listview在之前已經講過使用方法? 不清楚的同學可以先去看看Flutter學習(6)——Tab導航與ListView使用 | Stars-One的雜貨小窩

注: 本文基於Fluter1.2版本,只講解了Dio的get請求,之後再看看有沒有時間補充一波詳細的使用和例子吧

Dio介紹

dio是一個強大的Dart Http請求庫,支援Restful API、FormData、攔截器、請求取消、Cookie管理、檔案上傳/下載、超時、自定義介面卡等...

實現過程

1.get請求資料

這裡,我們使用最為簡單的get請求方式來獲取資料,介面的話我們使用郭霖大佬提供的API介面http://guolin.tech/api/china,我們可以使用瀏覽器直接訪問,來看看獲取的資料,如下圖所示

返回的資料是各大城市的相關資料,待會我們可以使用列表把城市名顯示出來即可

請求介面的程式碼如下

void getCityData() async {
    Response response;
    var dio = Dio();
    response = await dio.get('http://guolin.tech/api/china');
    print(response.data.toString());
}

因為這裡是資料是從介面獲取的,資料為動態的,這裡我們的頁面得使用StatefulWidget,則是在State類初始化initState方法的時候呼叫介面

程式碼跑起來,進到頁面,發現報錯了? 錯誤如下所示:

百度一看,是因為Android高版本不支援http協議的緣故,所以,按照之前的老套路,加個xml配置,調整即可,具體可參考Android 9 網路請求失敗 | Stars-One的雜貨小窩

按照上面的步驟配置後,再來試下(注意需要停止APP後重新進行編譯,然後再點debug或run的圖示,使用熱過載是不會起作用的)

ok,成功調通​,​資料​已經​列印​出來​了:happy:

2.實體類建立

之前我們Android開發的時候,使用的是Gson解析json字串,將json字串轉為對應的實體類,好方便我們取值,這裡,flutter同樣也是

這裡推薦使用個外掛JsonToDart進行實體類的生成,外掛地址

安裝好外掛後,我們要使用的話,可以右鍵,然後懸著具體選單即可新建即可,這裡我是建了個model資料夾,右鍵model資料夾, New -> Json To Dart

把json字串輸入進去,輸入類名,之後點選Generate即可生成一個dart的實體類檔案

以往Android開發中我們是使用Gson等框架,把json字串轉為實體類

而在flutter中,由於其內建有Json型別的資料,所以不必要再引入其他框架,使用jsonDecode方法即可

小提示:如果直接複製,jsonDecode可能會報錯,因為還沒有匯入,可以游標選擇jsonDecode,按下alt+enter,選擇import開頭的那個選單即可自動匯入

我們稍微改下程式碼,如下:

void getCityData() async {
    Response response;
    var dio = Dio();
    response = await dio.get('http://guolin.tech/api/china',options: Options(responseType: ResponseType.plain));
    var list = jsonDecode(response.data);
    var cityList = list.map((m) => new CityModel.fromJson(m)).toList();
    print(cityList);
}

這裡我們可以看到程式碼的第五行,傳了個options引數,options是為了設定返回的型別資料,如果沒有這個的話,Dio會自動將返回的資料轉為Json型別的物件

但是由於現在介面返回的一個Json陣列的字串,導致無法解析成功(平常介面都是一個json的字串,郭霖大佬寫得..? )

所以得采用此方法進行解析,之後將資料轉為List型別,裡面的每個資料都是實體類

3.列表展示

展示就比較簡單了,我們使用ListView即可,不過,需要注意的是,得提前在State類中定義好一個List陣列

介面請求到資料之後,更新此List陣列裡的資料即可達到更改UI的操作(注意使用setState()方法哦?)

void getCityData() async {
    var dio = Dio();
    Response response = await dio.get('http://guolin.tech/api/china',
        options: Options(responseType: ResponseType.plain));
    var list = jsonDecode(response.data);

    var cityList = list.map((m) => new CityModel.fromJson(m)).toList();
    //注意使用setState方法
    setState(() {
      //this.list是在State類中定義的
      this.list.addAll(cityList);
    });
}

效果圖

原始碼

import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_demo/model/city_model.dart';
import 'package:webview_flutter/webview_flutter.dart';

import 'MyMaterialPage.dart';

class DioTestPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return DioTestState();
  }
}

class DioTestState extends State<DioTestPage> {
  List list = [];

  @override
  Widget build(BuildContext context) {
    return MyMaterialPage("Dio獲取資料及展示", _listView());
  }

  @override
  void initState() {
    getCityData();
  }

  void getCityData() async {
    var dio = Dio();
    Response response = await dio.get('http://guolin.tech/api/china',
        options: Options(responseType: ResponseType.plain));
    var list = jsonDecode(response.data);

    var cityList =
    list.map((m) => new CityModel.fromJson(m)).toList();
    setState(() {
      this.list.addAll(cityList);
    });

  }

  Widget _listView() {
    return new ListView.builder(
      //listview的子項item數量
      itemCount: list.length,
      //內邊距
      padding: new EdgeInsets.all(5.0),
      itemBuilder: (BuildContext context, int index) {
        //返回每個子項item的widget
        //城市名
        return _listItemView(list[index].name);
      },
    );
  }

  Widget _listItemView(String name) {
    return Row(
      children: [
        Center(
          child: Text(name),
        ),
      ],
    );
  }
}

參考

相關文章