Skip to content

网络请求与数据存储

更换镜像源

通过环境变量配置国内镜像源,以下是具体实现方法及注意事项:

国内镜像源需通过设置以下两个环境变量实现:

  • PUB_HOSTED_URL:指定 Dart 包仓库镜像地址
  • FLUTTER_STORAGE_BASE_URL:指定 Flutter SDK 和依赖的镜像地址

常用镜像源列表(任选其一):

​清华大学 TUNA 协会

bash
export PUB_HOSTED_URL=https://mirrors.tuna.tsinghua.edu.cn/dart-pub
export FLUTTER_STORAGE_BASE_URL=https://mirrors.tuna.tsinghua.edu.cn/flutter

上海交大 SJTUG

bash
export PUB_HOSTED_URL=https://dart-pub.mirrors.sjtug.sjtu.edu.cn
export FLUTTER_STORAGE_BASE_URL=https://mirrors.sjtug.sjtu.edu.cn

阿里云

bash
export PUB_HOSTED_URL=https://mirrors.aliyun.com/dart-pub
export FLUTTER_STORAGE_BASE_URL=https://mirrors.aliyun.com/flutter

Flutter 社区主镜像

bash
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn

以 Mac 为例,将 export 命令添加到 ~/.bashrc~/.zshrc~/.profile 文件末尾,执行 source ~/.bashrcsource ~/.zshrcsource ~/.profile 生效。

执行以下命令后,观察下载速度是否提升,或通过日志检查是否命中镜像地址:flutter pub get

通过 HTTP 请求获取网络数据

通过 HTTP 请求获取网络数据,将数据渲染到页面上,需要使用 http 包。

dart
import 'dart:convert';

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

class HttpStudy extends StatefulWidget {
  const HttpStudy({super.key});

  @override
  State<HttpStudy> createState() => _HttpStudyState();
}

class _HttpStudyState extends State<HttpStudy> {
  var resultShow = "";
  var resultShow2 = "";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('基于HTTP实现网络操作-Flutter网络开发实战应用'),
      ),
      body: Column(
        children: [
          _doGetBtn(),
          _doPostBtn(),
          _doPostJsonBtn(),
          Text('返回的结果: $resultShow'),
          Text('解析的Msg: $resultShow2'),
        ],
      ),
    );
  }

  _doGetBtn() {
    return ElevatedButton(onPressed: _doGet, child: const Text('发送Get请求'));
  }

  _doPostBtn() {
    return ElevatedButton(onPressed: _doPost, child: const Text('发送Post请求'));
  }

  _doPostJsonBtn() {
    return ElevatedButton(
        onPressed: _doPostJson, child: const Text('发送Post请求'));
  }

  /// 发送Get请求
  void _doGet() async {
    var uri =
        Uri.parse('https://api.geekailab.com/uapi/test/test?requestPrams=11');
    var response = await http.get(uri);
    if (response.statusCode == 200) {
      setState(() {
        resultShow = response.body;
      });
    } else {
      setState(() {
        resultShow = '请求失败: code:${response.statusCode}, body${response.body}';
      });
    }
  }

  /// 发送Post请求
  void _doPost() async {
    var uri =
        Uri.parse('https://api.geekailab.com/uapi/test/test?requestParams=11');
    var params = {"requestParams": "doPost"};
    print("params:${params}");

    /// 数据格式要求为Map<string, string>
    var response = await http.post(uri, body: params);
    if (response.statusCode == 200) {
      setState(() {
        resultShow = response.body;
      });
    } else {
      setState(() {
        resultShow = '请求失败: code:${response.statusCode}, body${response.body}';
      });
    }
  }

  /// 发送Json类型的Post请求
  _doPostJson() async {
    var uri = Uri.parse('https://api.geekailab.com/uapi/test/testJson');
    var params = {"requestParams": "doPost"};
    var response = await http.post(
      uri,
      body: jsonEncode(params), /// Map转JSON字符串
      headers: {"content-type": "application/json"}, /// 设置请求头
    );
    if (response.statusCode == 200) {
      setState(() {
        resultShow = response.body;
      });

      /// 将Json字符串转为Map类型
      var map = jsonDecode(response.body);
      setState(() {
        resultShow2 = map['msg'];
      });
    } else {
      setState(() {
        resultShow = '请求失败: code:${response.statusCode}, body${response.body}';
      });
    }
  }
}

将Json字符串转换为 Map 和 Model

  • 将Json字符串转换为Map:利用 jsonDecode 方法将Json字符串转换为Map
  • 将Map转换为Json字符串:利用 jsonEncode 方法将Map转换为Json字符串
  • 将Map转换为Dart Model实体类:利用 fromJson 方法将Map转换为Dart Model实体类
dart
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_next_storage/dart_model.dart';

/// JSON解析与Dart Model 的使用
class JsonParsingPage extends StatefulWidget {
  const JsonParsingPage({super.key});

  @override
  State<JsonParsingPage> createState() => _JsonParsingPageState();
}

class _JsonParsingPageState extends State<JsonParsingPage> {
  var resultShow = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("JSON解析与Dart Model 的使用")),
      body: Column(
        children: [_json2MapBtn(), _json2ModelBtn(), Text('结果:${resultShow}')],
      ),
    );
  }

  _json2MapBtn() {
    return ElevatedButton(onPressed: _json2Map, child: const Text("Json转Map"));
  }

  _json2ModelBtn() {
    return ElevatedButton(
        onPressed: _json2Model, child: const Text("Json转Model实体类"));
  }

  void _json2Map() {
    var jsonString =
        '{"code":0,"data":{"code":0,"method":"GET","requestPrams":"11"},"msg":"SUCCESS."}';

    Map<String, dynamic> map = jsonDecode(jsonString);
    setState(() {
      resultShow =
          "code:${map['code']} jsonParams: ${map['data']['requestPrams']}";
    });
  }

  void _json2Model() {
    var jsonString =
        '{"code":200,"data":{"code":0,"method":"GET","requestPrams":"11"},"msg":"SUCCESS."}';

    /// 将Json转成Map
    Map<String, dynamic> map = jsonDecode(jsonString);

    /// 将Map转成Dart Model实体类
    DataModel dataModel = DataModel.fromJson(map);
    setState(() {
      resultShow =
          'code:${dataModel.code}; requestPrams:${dataModel.data?.requestPrams}';
    });
  }
}

FutureBuilder 的使用

FutureBuilder 是 Flutter 中用于处理异步操作的组件,它可以帮助我们在异步操作完成之前显示一个加载状态,并在异步操作完成后更新UI。

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

class FutureStudy extends StatefulWidget {
  const FutureStudy({super.key});

  @override
  State<FutureStudy> createState() => _FutureStudyState();
}

class _FutureStudyState extends State<FutureStudy> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Future与FutureBuilder实战应用')),
      body: FutureBuilder<DataModel>(
        future: fetchGet(),
        builder: (BuildContext context, AsyncSnapshot<DataModel> snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.none:
              return const Text('state none');
            case ConnectionState.waiting:
              return const Center(
                child: CircularProgressIndicator(),
              );
            case ConnectionState.active:
              return const Text('state active');
            case ConnectionState.done:
              if (snapshot.hasError) {
                return Text(
                  '${snapshot.error}',
                  style: const TextStyle(color: Colors.red),
                );
              } else {
                print('snapshot.data${snapshot.data}');
                return Column(
                  children: [
                    Text('code:${snapshot.data?.code}'),
                    Text('requestParams:${snapshot.data?.data?.requestPrams}')
                  ],
                );
              }
          }
        },
      ),
    );
  }

  Future<DataModel> fetchGet() async {
    var uri =
        Uri.parse('https://api.geekailab.com/uapi/test/test?requestPrams=11');
    final response = await http.get(uri);
    var result = jsonDecode(response.body);
    return DataModel.fromJson(result);
  }
}

shared_preferences 的使用

shared_preferences 是 Flutter 中用于存储和读取简单数据(如字符串、整数、浮点数等)的库。它提供了一个简单的键值对存储系统,可以用于保存和检索应用程序的配置数据。

首先在 pubspec.yaml 文件中添加包声明,然后执行 flutter pub get 命令。

yaml
dependencies:
  shared_preferences: ^2.2.3

常用的API:

  • SharedPreferences.getInstance():获取 SharedPreferences 实例
  • setInt:设置整数类型的值
  • getInt:获取整数类型的值
  • setString:设置字符串类型的值
  • getString:获取字符串类型的值
dart
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesStudy extends StatefulWidget {
  const SharedPreferencesStudy({super.key});

  @override
  State<SharedPreferencesStudy> createState() => _SharedPreferencesStudyState();
}

class _SharedPreferencesStudyState extends State<SharedPreferencesStudy> {
  String countString = '';
  String localCount = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('基于shared_perferences实现计数器')),
      body: Column(
        children: [
          ElevatedButton(
              onPressed: _incrementCounter,
              child: const Text('Increment Counter')),
          ElevatedButton(
              onPressed: _getCounter, child: const Text('Get Counter')),
          Text(
            countString,
            style: const TextStyle(fontSize: 20),
          ),
          Text(
            "result:${localCount}",
            style: const TextStyle(fontSize: 20),
          )
        ],
      ),
    );
  }

  void _incrementCounter() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      countString = "$countString 1";
    });
    int counter = (prefs.getInt('counter') ?? 0) + 1;
    await prefs.setInt('counter', counter);
  }

  _getCounter() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      localCount = prefs.getInt('counter').toString();
    });
  }
}