http
大约 4 分钟flutter
依赖
在项目依赖配置文件 pubspec.yaml 中添加如下的 http 依赖,类似 maven 添加依赖,记得执行 pub get 拉取依赖到项目源码
dependencies:
flutter:
sdk: flutter
http: ^0.13.5
规范
实体类
制作实体类 lib\entity\repair_main_dto.dart,同 java 规范不同,单词都使用小写,以下划线作为分隔符,模板代码如下,大体类似 java 实体类
构造函数 - 和类同名的方法
RepairMainDtomap数据转实体类 - 方法RepairMainDto.fromJson实体类转
map数据 - 方法toJsontoString方法
// RepairMainDto = java后台实体类 RepairMaindto
// 此处只设置用得到的属性 progress
class RepairMainDto {
int? id;// repair_main 主键字段 id
String? progress;// repair_main 字段 progress
// 构造方法
RepairMainDto({this.id,this.progress});
// 静态构造方法,将 http 请求的响应数据转换为实体类对象
factory RepairMainDto.fromJson(Map<String,dynamic> map){
return RepairMainDto(
id: map['id'],
progress: map['progress'],
);
}
Map<String,dynamic> toJson(){
Map<String,dynamic> ret = {};
ret['id'] = id;
ret['progress'] = progress;
return ret;
}
String toString() {
return 'RepairMainDto:{id:$id,progress:$progress}';
}
}
dao
类似 java 的 dao,不同处在于 java 的 dao 负责和数据库通信,这里的 dao 也是获取数据,不过是通过发送 http 请求获取数据。制作类 lib\dao\repair_main_dao.dart 代码如下
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:snbc_ems_pda_annex/entity/repair_main_dto.dart';
class RapairMainDao {
static Future<RepairMainDto> fetch({required num id}) async {
// 请求报修记录
String uri = 'http://192.168.110.200/snbcemsbe/repairMain/selectBydto/$id';
var url = Uri.parse(uri);
final res = await http.post(url);
print(res.toString());
Utf8Decoder utf8decoder = const Utf8Decoder();
String bodyStr = utf8decoder.convert(res.bodyBytes);
if(res.statusCode != 200) throw Exception(bodyStr);
var map = jsonDecode(bodyStr);// 开发者后台响应来的响应结果,.data 是实际的数据
print(map);
return RepairMainDto.fromJson(map['data']);
}
}
调用
最后在业务组件中调用 dao
import 'package:snbc_ems_pda_annex/utils/device_utils.dart';
import 'package:snbc_ems_pda_annex/dao/repair_main_dao.dart';
Future<void> _getRepairMain() async {
final RepairMainDto repairMainDto = await RapairMainDao.fetch(id: 7);
print(repairMainDto);
}
最简案例
新创建的项目在入口文件 main.dart 的入口方法 build 的属性 home 后面填写自己制作的 widget ,填写后的 main.dart 的完整代码如下
import 'package:flutter/material.dart';
import 'package:netstorage/http.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const HttpStudy(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
下面是自己制作的演示 http 用法的代码
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class HttpStudy extends StatefulWidget {
const HttpStudy({super.key});
State<HttpStudy> createState() => _HttpStudyState();
}
class _HttpStudyState extends State<HttpStudy> {
var httpRes = '';
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('演示Http网络请求')),
body: Column(children: [
_doGetBtn(),
Text('htt请求来的响应:$httpRes')
],),
);
}
// 创建按钮
_doGetBtn(){
return ElevatedButton(onPressed: _doGet, child: const Text('发送GET请求'));
}
_doGet() async {
print('_doGet');
var uri = Uri.parse('https://showawx.xdfznh.club/visitorbe/test/now');
var res = await http.get(uri);
print('请求得到的响应:${res.toString()}');
if(res.statusCode == 200){
// res.body 是开发人员后台响应的数据
print('请求成功,body:${res.body}');
setState(() {
httpRes = res.body;
});
}else{
setState(() {
httpRes = '请求失败,code:${res.statusCode},body:${res.body}';
});
}
}
}
post请求
后端接受 json 类型的参数则需要在 body 中转换为 json 形式。如果是 x-www-form-urlencoded 类型则不需要 jsonEncode (json 时此处是 application/json),注意通过 headers 指定是 json 形式
_doPost() async {
var uri = Uri.parse('https://www.xdfznh.club/wxpadbe/dev/proxyUrl');
var params = {'rawUrl':'https://www.xdfznh.club'};
var res = await http.post(
uri,
body: jsonEncode(params),
headers: {
'Content-Type': 'application/json; charset=UTF-8', // 关键:设置 Content-Type
},
);
if(res.statusCode == 200){
print('请求来的响应:${res.body}');
setState(() {
postRes = res.body;
});
}else{
setState(() {
postRes = 'post请求异常,code:${res.statusCode},msg:${res.body}';
});
}
}
json反序列化为map
注意下面 jsonDecode 后的 map 对象要使用中括号获取属性的值
_doGet() async {
print('_doGet');
var uri = Uri.parse('https://showawx.xdfznh.club/visitorbe/test/now');
var res = await http.get(uri);
print('请求得到的响应:${res.toString()}');
if(res.statusCode == 200){
// res.body 是开发人员后台响应的数据
print('请求成功,body:${res.body}');
setState(() {
getRes = res.body;
});
// json 数据反序列化
var data = jsonDecode(res.body);
print('data:${data}');
var success = data['success'];
var msg = data['msg'];
print('success:$success,msg:$msg');
}else{
setState(() {
getRes = '请求失败,code:${res.statusCode},body:${res.body}';
});
}
}
处理响应结果的中文
下面是登录请求,最后几行处理响应结果的中文
static login({required String username, required String password}) async {
Map<String,String> reqData = {'email':'chanchaw@126.com','password':'eVF4TJ'};
var uri = Uri.parse(url);
var res = await http.post(
uri,
body: jsonEncode(reqData),
headers: {
'Content-Type': 'application/json; charset=UTF-8', // 关键:设置 Content-Type
},
);
if(res.statusCode == 200) print('请求来的响应:${res.body}');
else print('登录请求异常,code:${res.statusCode},msg:${res.body}');
// 处理中文
Utf8Decoder utf8decoder = const Utf8Decoder();
String bodyString = utf8decoder.convert(res.bodyBytes);
print('处理中文后的响应结果:$bodyString');
}
DAO模板代码
http 请求获取数据的步骤如下:
- 请求
http - 使用
utf8处理中文 - 响应
http状态码200则返回字符串结果,由业务组件解析为实体类 - 没有权限 401 则跳转到登录页面
- 其他错误码则抛出提示
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:netstorage/utils/navigator_utils.dart';
class HomeDao {
// 请求首页数据
static Future<String?> fetch() async {
var url = Uri.parse('请求主页数据的URI');
final res = await http.get(url);
Utf8Decoder utf8decoder = const Utf8Decoder();
String bodyStr = utf8decoder.convert(res.bodyBytes);
print('请求首页数据的响应结果:$bodyStr');
if(res.statusCode == 200) return bodyStr;
if(res.statusCode == 401) {
NavigatorUtils.goLogin();
return null;
}
throw Exception(bodyStr);
}
}
