Inscription — the sword of the world, from your accumulation of a little start, and the place, will strive for excellence, that is, toss about every day.

Important message

  • Web request analysis video tutorial in THE DIO usage of Flutter is here
  • Video on UI basics of Developing an APP from The introduction to Flutter
  • From the introduction of Flutter to the development of an APP
  • The series of articles on the Cross-platform development of Flutter bit by bit is here

This article will cover 1. Sending basic GET requests using DIO 2. Sending get requests using DIO 3. Parse the response JSON data. 4. Use DIO to send the POST request and submit the FormData parameter 5. Use DIO to send POST request and submit JSON parameter 6. Use DIO to upload files and realize progress listening 7. Use DIO to download files and implement progress monitoring 8. Configure dio interceptor 9. Configure dio network proxy packet capture. 10. Configure DIO request header and common request parameters

1 the introduction

Dio’s framework for accessing the web in the Cross-platform development of the Flutter, we first introduced dependencies

Dio: 3.0.9Copy the code
2 Dio Get request
2.1 Dio GET Request No parameter
  // The get request has no parameters
  void getRequestFunction1(a) async {
    /// Create Dio object
    Dio dio = new Dio();
    /// Request the address to get the list of users
    String url = "http://192.168.0.102:8080/getUserList";
    /// Initiate a GET request
    Response response = await dio.get(url);
    /// Response data
    var data = response.data;

    setState(() {
      result = data.toString();
    });
  }
Copy the code

Data response result

{
    "code": 200."data": [{"id": 3."userName": "Tester"."realName": "Zhang"."age": 22}]."message": "Request successful"
}
Copy the code

Breakpoint debugging is as follows

2.2 Dio GET request has parameters
  /// The get request has parameters
  /// Obtain user information based on user ID
  void getRequestFunction2(a) async {
    / / / user id
    int userId =3;
    / / / to create a dio
    Dio dio = new Dio();
    /// Request the address
    /// Pass parameter 1
    String url = "http://192.168.0.102:8080/getUser/$userId";
    /// Pass parameter 2
    String url2 = "Http://192.168.0.102:8080/getUser? userId=$userId";
    /// Pass parameter 3
    String url3 = "http://192.168.0.102:8080/getUser";

    Map<String,dynamic> map = Map();
    map["userId"]= userId;
    /// Initiate a GET request
    Response response = await dio.get(url3,queryParameters: map);

    /// Response data
    Map<String,dynamic> data = response.data;
    /// Parse the response data into a UserBeanUserBean userBean = UserBean.fromJson(data); }}Copy the code

In the above code, parameter passing mode 1 and parameter passing mode 2 are to concatenate the parameters in the request link, and request mode 3 is to put the parameters in a map and then configure the parameters through Dio queryParameters. The data structure returned above is

{
    "code": 200."data": {
        "id": 3."userName": "Tester"."realName": "Zhang"."age": 22
    },
    "message": "Request successful"
}
Copy the code

Breakpoint debugging


class UserBean{
  String userName;
  String realName;
  int age;
  int id;

  static UserBean fromJson(Map<String,dynamic> rootData){
    /// Parse the first layer
    Map<String,dynamic> data = rootData["data"];
    /// Parse the second layer
    UserBean userBean = new UserBean();

    userBean.id = data["id"];
    userBean.age = data["age"];
    userBean.userName= data["userName"];
    userBean.realName = data["realName"];
    returnuserBean; }}Copy the code

The data parsing in the UserBean is shown in the figure below

3 Dio Post request
2.1 Dio post requests to submit FormData FormData

FormData combines the submitted parameters name and value to serialize the FormData. Thus reducing the concatenation of form elements can also be described as follows: The FormData interface provides a way to construct key-value pairs representing form data, requests made through FormData are coded as “multipart/form-data”, and in network requests, This value is recorded by the content-type, which can be interpreted as the content-type represents the media Type information in the specific request.

The content-type we often use in actual development is as follows

Multipart /form-data Application/JSON Json data format Application/X-wwW-form-urlencoded form data formatCopy the code

Next we will use dio to initiate a post request with the submission parameter format FromData

  void postRequestFunction(a) async {
    / / / to create a Dio
    Dio dio = new Dio();
    / / / send FormData:
    FormData formData = FormData.fromMap({"name": "Zhang"."age": 22});
    String url ="http://192.168.200.68:8080/registerUser";
    /// Initiate a POST request with the registered user information
    Response response = await dio
        .post(url, data: formData);
    result = response.data.toString();
    setState(() {});
  }

Copy the code

The captured packets are as follows

2.2 Dio Post Requests to submit JSON data

Next, we use dio to initiate a POST request and submit the parameters in JSON format

  /// Post requests to send JSON
  void postRequestFunction2(a) async{
    String url = "http://192.168.0.102:8080/registerUser2";
    / / / to create a Dio
    Dio dio = new Dio();
    /// Create a Map to encapsulate parameters
    Map<String,dynamic> map = Map();
    map['userName'] ="Xiao Ming";
    map['userAge'] =44;

    /// Initiates a POST request
    Response response =  await dio.post(url,data: map);

    var data = response.data;
  }
Copy the code

The captured packets are as follows

4 Dio file upload and progress monitoring

  /// The picture in the mobile phone
  String localImagePath ="/storage/emulated/0/Download/17306285.jpg";
  /// Upload server address
  String netUploadUrl = "http://192.168.0.102:8080/fileupload";

  ///dio implements file upload
  void fileUplod(a) async{
    / / / to create a Dio
    Dio dio = new Dio();

    Map<String ,dynamic> map = Map();
    map["auth"] ="12345";
    map["file"] = await MultipartFile.fromFile(localImagePath,filename: "xxx23.png");
    / / / by FormData
    FormData formData = FormData.fromMap(map);
    / / / send the post
    Response response = await dio.post(netUploadUrl, data: formData,
      /// Here is the send request callback function
      ///[progress] Indicates the current progress
      / / / / total total progress
      onSendProgress: (int progress, int total) {
        print("The current progress is $progress and the total progress is $total"); });/// Server response result
    var data = response.data;

  }

Copy the code

Debug through breakpoints

5 download Dio files and monitor progress

  /// Current progress Percentage The current progress/total progress ranges from 0 to 1
  double currentProgress =0.0;
  /// The network path to download the file
  String apkUrl ="";
  /// Use dio to download files
  void downApkFunction(a) async{
    /// Apply for file write permission
    bool isPermiss =  await checkPermissFunction(a);
    if(isPermiss) {
      /// Mobile phone storage directory
      String savePath = await getPhoneLocalPath(a);
      String appName = "rk.apk";

      / / / to create a DIO
      Dio dio = new Dio();

      /// Parameter a file's network storage URL
      /// Parameter 2 download the local directory file
      /// Parameter 3 download listener
      Response response = await dio.download(
          apkUrl, "$savePath$appName", onReceiveProgress: (received, total) {
        if(total ! = -1) {
          /// The percentage of current downloads
          print((received / total * 100).toStringAsFixed(0) + "%");
          / / CircularProgressIndicator (value: currentProgress,) progress 0 to 1currentProgress = received / total; setState(() { }); }}); }else{
      /// Prompt the user to agree to the permission application}}Copy the code

There are three types of Android permissions: normal permissions, dangerous permissions, and special permissions

Normal permissions permissions that can be obtained by configuring directly in the AndroidManifest. This is where most of the permissions go. Dangerous permissions. Some permissions were defined here after Android 6.0. Dangerous permissions not only need to be configured in the AndroidManifest, but also need to check whether you really have permissions before using, to dynamically apply.

On ios, use Xcode to open this directory

Select the info.plist file in the Xcode project, right-click Open as-source Code, and copy the permission configured Code into it. The contents in the key and value pairs can be modified according to the project requirements.

<! - photo album - > 
<key>NSPhotoLibraryUsageDescription</key> 
<string>Your consent is required for the APP to access the album</string> 
<! - camera - > 
<key>NSCameraUsageDescription</key> 
<string>Your consent is required for the APP to access the camera</string> 
<! -- Microphone --> 
<key>NSMicrophoneUsageDescription</key> 
<string>Your consent is required for the APP to access the microphone</string> 
<! - position - > 
<key>NSLocationUsageDescription</key> 
<string>Your consent is required for the APP to access the location</string> 
<! -- Access location during use --> 
<key>NSLocationWhenInUseUsageDescription</key> 
<string>The App requires your consent before the App can access the location during use</string> 
<! -- Always access location --> 
<key>NSLocationAlwaysUsageDescription</key> 
<string>The App needs your consent before the App can always access the location</string> 
<! -- -- -- > calendar 
<key>NSCalendarsUsageDescription</key> 
<string>The App needs your consent before the App can access the calendar</string> 
<! -- Reminders --> 
<key>NSRemindersUsageDescription</key> 
<string>Your consent is required for the APP to access reminders</string> 
<! -- Sports and Fitness --> 
<key>NSMotionUsageDescription</key> 
<string>Your consent is required for the APP to access sports and fitness</string> 
<! -- Health Update --> 
<key>NSHealthUpdateUsageDescription</key> 
<string>Your consent is required for the APP to access health updates</string> 
<! -- Sharing health --> 
<key>NSHealthShareUsageDescription</key> 
<string>Your consent is required for the APP to access health share</string> 
<! Bluetooth - > - 
<key>NSBluetoothPeripheralUsageDescription</key> 
<string>Your consent is required for the APP to access bluetooth</string> 
<! -- Media Database --> 
<key>NSAppleMusicUsageDescription</key> 
<string>Your consent is required for the APP to access the media database</string>
Copy the code

In the Flutter project directory, we can also open the info.plist file configuration, as shown in the figure below

Permission_handler: ^ 4.3.0Copy the code

The permission code is as follows

  / / / PermissionGroup. Storage is
  // External Storage for Android
  // Ios Documents' or 'Downloads'
  checkPermissFunction() async {
    if (Theme.of(context).platform == TargetPlatform.android) {
      /// The Android platform checkPermissionStatus method verifies whether the storage card has read and write permission
      PermissionStatus permission = await PermissionHandler(a)
          .checkPermissionStatus(PermissionGroup.storage);
      if(permission ! = PermissionStatus.granted) {/// permissions are not allowed. Call requestPermissions to request permission
        Map<PermissionGroup, PermissionStatus> permissions =
            await PermissionHandler(a)
                .requestPermissions([PermissionGroup.storage]);
        /// Verify user processing of permission application
        if (permissions[PermissionGroup.storage] == PermissionStatus.granted) {
          return true; }}else {
        return true; }}else {
      return true;
    }
    return false;
  }
Copy the code

Once permissions have been applied, we need to determine the path to the storage card, in this case using the path_provider plug-in

Path_provider: 1.6.0Copy the code
  /// Obtain the storage directory path of the mobile phone
  / / / external.getexternalstoragedirectory () to obtain the android's External Storage (External Storage)
  / / / getApplicationDocumentsDirectory obtained is ios Documents ` or ` Downloads ` directory
  Future<String> getPhoneLocalPath(a) async {
    final directory = Theme.of(context).platform == TargetPlatform.android
        ? await getExternalStorageDirectory(a)
        : await getApplicationDocumentsDirectory(a);
    return directory.path;
  }
Copy the code
6 DIO Configuration network proxy packet capture
  _setupPROXY(Dio dio) {
    (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (HttpClient client) {
      client.findProxy = (uri) {
        /// 192.168.0.102:8888 is our proxy service address
        return "The PROXY 192.168.0.102:8888";
      };
      client.badCertificateCallback =
          (X509Certificate cert, String host, int port) {
        return true;
      };
    };
  }
Copy the code
7 DIO Configures common request parameters

In practical application development, we will have parameters such as token, appVersionCode, etc., which need to be passed for each interface request, which are called public request parameters. In this case, we can consider to configure dio request in this way

  String application = 1.2.2 "V";
  int appVersionCode = 122;
  ///[url] A network request link
  ///[data] Indicates the JSON data transmitted during the POST request
  ///[queryParameters] Get Specifies the parameters passed during the request
  void configCommonPar(url,data,Map<String, dynamic> queryParameters){
    /// Set uniform parameters
    if(data ! =null) {
      data['application'] = application;
      data['appVersionCode'] = appVersionCode.toString();
    } else if(queryParameters ! =null) {
      queryParameters['application'] = application;
      queryParameters['appVersionCode'] = appVersionCode.toString();
    } else {
      /// It is possible to concatenate other parameters in the URL
      if (url.contains("?")) {
        url += "&application=$application&appVersionCode=$appVersionCode";
      } else {
        url += "? application=$application&appVersionCode=$appVersionCode"; }}}}Copy the code
8 DIO Configures the Content-type and request header

When we create the Dio object, we initialize a BaseOptions to create the Dio

      BaseOptions options = BaseOptions();
      /// Request header configuration
      options.headers["appVersionCode"] =406;
      options.headers["appVersionName"] ="V 4.0.6";
      
      options.contentType="application/json";
      options.method="GET";
      options.connectTimeout=30000;
      / / / to create a dio
      Dio dio = new Dio(options);
Copy the code

We can also get the default options from dio and modify them each time we send a different request such as GET, POST, etc

void getRequestFunction2(a) async {
    / / / user id
    int userId = 3;
    / / / to create a dio
    Dio dio = new Dio();

    /// Request the address
    /// Pass parameter 1
    String url = "http://192.168.0.102:8080/getUser/$userId";
    /// Modify contentType here
    dio.options.contentType="application/json";
    /// Request header configuration
    dio.options.headers["appVersionCode"] =406;
    dio.options.headers["appVersionName"] ="V 4.0.6";
    /// Initiate a GET requestResponse response = await dio.get(url); . }Copy the code
9 Dio cancellations the network request

In actual development, for example, when we exit a page, if the network request is not complete, we have a memory leak, so we have to cancel the network request when the page is destroyed, or when downloading a file, it takes too long, and the user clicks Cancel, and we have to cancel the network connection

/// Create a cancel flag
CancelToken cancelToken = new CancelToken();
void getRequestFunction2(a) async {
    / / / user id
    int userId = 3;
    / / / to create a dio
    Dio dio = new Dio();
    /// Request the address
    /// Pass parameter 1
    String url = "http://192.168.0.102:8080/getUser/$userId";
    /// Initiate the GET request and set the CancelToken cancellation flagResponse response = await dio.get(url,cancelToken: cancelToken); . }Copy the code

So when we need to manually cancel the network request, we just call the following method

   // Cancel the network request
   if(cancelToken! =null&&! cancelToken.isCancelled){ cancelToken.cancel(); cancelToken=null;
    }
Copy the code

Note that a cancelToken can only be used for one network request.


The completion of