Flutter JSON 字符串和 Map 类型的转换
// 使用 dart:convert 包来实现 JSON 与 Map 之间的转换
import 'dart:convert';
var mapData = {"name": "张三", "age": "20"};
var strData = '{"name":"张三","age":"20"}';
// 使用 json.encode() 将 Map 转换为 JSON 字符串
print(json.encode(mapData));
// 使用 json.decode() 将 JSON 字符串转化为 Map 类型
print(json.decode(strData));
Flutter 使用官方http库进行网络请求
// 官方http库的使用方法可参考其官方文档链接
https://pub.dev/packages/http
Flutter Dio 库的介绍
// Dio 是 Dart 的强大的 HTTP 请求库,提供了多种高级功能
// Dio 支持如下特性:
// - Restful API
// - FormData
// - 请求拦截器
// - 请求取消
// - Cookie 管理
// - 文件上传/下载
// - 超时管理
// - 自定义适配器等等...
// 可以在以下链接查看 Dio 的详细文档和源代码
https://pub.dev/packages/dio
Dio 官方中文文档
使用官方http库的Flutter代码示例
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class HttpPage extends StatefulWidget {
HttpPage({Key key}) : super(key: key);
_HttpDemoState createState() => _HttpDemoState();
}
class _HttpDemoState extends State<HttpPage> {
List _list = [];
@override
void initState() {
super.initState();
this._getData();
}
_getData() async {
// 定义API的请求URL
var apiUrl = "http://a.itying.com/api/productlist";
// 使用http库发送GET请求
var result = await http.get(apiUrl);
// 判断请求是否成功
if (result.statusCode == 200) {
print(result.body);
setState(() {
this._list = json.decode(result.body)["result"];
});
} else {
print("请求失败,状态码: ${result.statusCode}");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("请求数据Demo"),
),
// 判断数据是否加载完成,完成则展示ListView,否则显示加载中...
body: this._list.length > 0
? ListView(
children: this._list.map((value) {
return ListTile(
title: Text(value["title"]),
);
}).toList(),
)
: Text("加载中...")
);
}
}
Flutter 使用Dio库进行HTTP请求
// 使用 dio 3.0.9 版本,首先在pubspec.yaml中添加
// dio: ^3.0.9
// 导入必要的包
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
// 定义UpDown StatefulWidget
class UpDown extends StatefulWidget {
UpDown({Key key});
_UpDown createState() => _UpDown();
}
class _UpDown extends State<UpDown> {
var list = [];
var page = 1;
var pageFlag = true;
var _scrollController = ScrollController();
@override
void initState() {
super.initState();
_getData();
// 上拉加载逻辑
_scrollController.addListener(() {
var _scrollTop = _scrollController.position.pixels; // 获取滚动条下拉的距离
var _scrollHeight = _scrollController.position.maxScrollExtent; // 获取整个页面的高度
if(_scrollTop >= _scrollHeight - 20) {
_getData();
}
});
}
// 获取数据方法
_getData() async {
if(pageFlag == false) return; // 判断是否有更多数据可加载
var response = await Dio().get('http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=${page}');
var res = json.decode(response.data)['result'];
setState(() {
list.addAll(res);
page++;
});
if(res.length < 20) {
setState(() {
pageFlag = false; // 若返回数据少于20条,则表示没有更多数据了
});
}
}
// 下拉刷新方法
Future<void> _onRefresh() async {
await Future.delayed(
Duration(milliseconds: 2000), () {
list = [];
page = 1;
_getData();
}
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('上拉加载-下拉刷新')),
body: list.length > 0 ? RefreshIndicator(
onRefresh: _onRefresh,
child: ListView.builder(
controller: _scrollController,
itemCount: list.length,
itemBuilder: (context, index) {
return Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 5, bottom: 5, left: 5),
alignment: Alignment.centerLeft,
child: Text('${list[index]['title']}', maxLines: 1, overflow: TextOverflow.ellipsis),
),
Divider(),
index == list.length - 1 ? getMoreTips(flag: this.pageFlag) : SizedBox()
],
);
},
),
) : getMoreTips(flag: this.pageFlag)
);
}
}
// 底部加载更多提示组件
class getMoreTips extends StatelessWidget {
var flag = true;
getMoreTips({Key key, this.flag}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: flag ? Row( // 若flag为true,显示加载中,否则显示没有更多数据
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('正在加载...'),
SizedBox(width: 10),
CircularProgressIndicator(strokeWidth: 2)
],
) : Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('没有更多数据了'),
SizedBox(height: 10),
],
),
);
}
}
Dio封装完成的代码 带拦截器 可以直接复制使用
import 'dart:convert';
import 'package:dio/dio.dart';
import 'utils.dart';
class DioHttp {
Dio _dio = Dio();
DioHttp() {
_initOptions();
_addInterceptors();
}
void _initOptions() async {
var tokens = await Storage.getString('token');
_dio.options.baseUrl = ''; // TODO: 设置为你的baseURL
_dio.options.connectTimeout = 15000;
_dio.options.receiveTimeout = 15000;
// 可以在这里添加公共的 header 和其他设置
_dio.options.headers = {
'Authorization': 'Bearer your_token_here',
'Custom-Header': 'custom_value',
};
_dio.options.contentType = 'application/x-www-form-urlencoded';
_dio.options.queryParameters = {
'api_key': 'your_api_key',
};
}
void _addInterceptors() {
_dio.interceptors.add(
InterceptorsWrapper(
onRequest: (options) async {
// 在这里添加你的token或者其他请求之前需要设置的信息
// options.headers["token"] = tokens; // 示例
return options;
},
onResponse: (response) {
return response; // 在这里对返回的数据进行处理,转换成你需要的格式
},
onError: (error) {
formatError(error); // 在这里统一处理错误
return error;
},
),
);
}
Future _request(String method, String url,
{Map<String, dynamic> data, Function success, Function error}) async {
try {
Response response;
if (method == 'GET') {
response = await _dio.get(url, queryParameters: data);
} else if (method == 'POST') {
response = await _dio.post(url, data: data);
}
if (response.statusCode == 200) {
var res = json.decode(response.data)['result'];
if (success != null) {
success(res);
}
} else {
if (error != null) {
error(response);
}
}
} catch (e) {
if (error != null) {
error(e);
}
}
}
Future get(String url,
{Map<String, dynamic> data, Function success, Function error}) async {
return _request('GET', url, data: data, success: success, error: error);
}
Future post(String url,
{Map<String, dynamic> data, Function success, Function error}) async {
return _request('POST', url, data: data, success: success, error: error);
}
// 下载文件
Future download(String url, String saveUrl,
{Function success, Function error, onReceiveProgress}) async {
try {
var response = await _dio.download(
_dio.options.baseUrl + url, saveUrl,
onReceiveProgress: onReceiveProgress ?? () {},
);
if (response.statusCode == 200) {
var res = json.decode(response.data)['result'];
if (success != null) {
success(res);
}
} else {
if (error != null) {
error(response);
}
}
} catch (e) {
if (error != null) {
error(e);
}
}
}
// 使用FormData发送POST请求
Future formData(String url, FormData data,
{Function success, Function error}) async {
return _request('POST', url, data: data, success: success, error: error);
}
void formatError(DioError e) {
if (e.type == DioErrorType.CONNECT_TIMEOUT) {
print("连接超时");
} else if (e.type == DioErrorType.SEND_TIMEOUT) {
print("请求超时");
} else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
print("响应超时");
} else if (e.type == DioErrorType.RESPONSE) {
print("出现异常404 503");
} else if (e.type == DioErrorType.CANCEL) {
print("请求取消");
} else {
print("未知错误");
}
}
}
final dioHttp = DioHttp(); // 创建DioHttp的单例,供全局使用
get请求使用方法
dioHttp.get('https://api.example.com/items',
data: {'param1': 'value1'},
success: (data) {
print('Request successful with data: $data');
},
error: (error) {
print('Request failed with error: $error');
}
);
post请求使用方法
dioHttp.post('https://api.example.com/items',
data: {'key1': 'value1', 'key2': 'value2'},
success: (data) {
print('Request successful with data: $data');
},
error: (error) {
print('Request failed with error: $error');
}
);
download请求使用方法
dioHttp.download('下载的文件的相对路径', '保存文件的绝对路径',
onReceiveProgress: (received, total) {
if (total != -1) {
print("${(received / total * 100).floor()}%");
}
},
success: (res) {
print("下载成功:$res");
},
error: (err) {
print("下载错误:$err");
}
);
formData请求使用方法
var formData = FormData.fromMap({
'file': await MultipartFile.fromFile('文件的绝对路径', filename: 'filename.png'),
'name': 'sample',
});
dioHttp.formData('您的API的相对路径', formData,
success: (res) {
print("成功:$res");
},
error: (err) {
print("错误:$err");
}
);