一、本地文件操作:
1.File文件操作:
说明:
临时目录:getTemporaryDirectory()
文档目录:getApplicationDocumentsDirectory()
外部存储目录(iOS不支持):getExternalStorageDirectory()
(1)添加PathProvider依赖,在pubspec.yaml中:
dependencies:
path_provider: ^2.0.11
(2)文件读写:
void editFile() async {
String dir = (await getApplicationDocumentsDirectory()).path; // 获取文档目录
File file = await File('$dir/counter.txt'); //获得文件对象
String content = await file.readAsString(); // 读取文件内容
content = content + "新内容";
file.writeAsString(content); //修改文件内容
}
2.Shared Preferences数据存储/获取:
说明:
存储位置:.../包名/shared_prefs/xxx.xml
(1)添加shared_preferences插件依赖,在pubspec.yaml中:
dependencies:
shared_preferences: ^2.0.15 #preferences存储库
(2)shared_preferences数据增删查工具类:
class SharedPreferenceUtil {//shared_preferences数据增删查工具类
late SharedPreferences _sharedPrefs; //Shared Preference操作类
void init() async {
_sharedPrefs = await SharedPreferences.getInstance();
}
void setInt(String key, int value) {
_sharedPrefs.setInt(key, value);
}
int? getInt(String key) {
return _sharedPrefs.getInt(key);
}
void setBool(String key, bool value) {
_sharedPrefs.setBool(key, value);
}
bool? getBool(String key) {
return _sharedPrefs.getBool(key);
}
void setDouble(String key, double value) {
_sharedPrefs.setDouble(key, value);
}
double? getDouble(String key) {
return _sharedPrefs.getDouble(key);
}
void setString(String key, String value) {
_sharedPrefs.setString(key, value);
}
String? getString(String key) {
return _sharedPrefs.getString(key);
}
void setStringList(String key, List<String> value) {
_sharedPrefs.setStringList(key, value);
}
List<String>? getStringList(String key) {
return _sharedPrefs.getStringList(key);
}
void remove(String key) {
_sharedPrefs.remove(key);
}
}
(3)使用工具类存储/读取数据:
...
SharedPreferenceUtil sharedPrefs = SharedPreferenceUtil(); //创建工具类
...
sharedPrefs.init(); //初始化
...
sharedPrefs.setString("key", "value"); //存储数据
String? value = sharedPrefs.getString("key"); //读取数据
...
二、HTTP网络请求:
1.使用dio库实现:
(1)添加dio库依赖,在pubspec.yaml中:
dependencies:
dio: ^4.0.6 #dio HTTP网络库
(2)使用dio实现网络请求:
class DioNetUtil {
Dio dio = Dio();
Map<String, CancelToken?> requestMap = {}; //取消标志,用于取消请求
//添加代理主机,通过代理主机转发请求
void _addProxy(HttpClient httpClient){
httpClient.findProxy = (uri) {
return "PROXY IP:端口"; //代理主机
//return "DIRECT"; //不需要代理主机时返回"DIRECT"
};
}
//添加证书校验
void _verifyCer(HttpClient httpClient, String cerContent) {
httpClient.badCertificateCallback = (X509Certificate cert, String host, int port) {
if(cert.pem != cerContent) return false; //证书校验失败
return true; //证书校验通过,放行
};
}
//外部调用,添加证书校验
void initCerVerify(String cerContent){
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
//添加代理主机,通过代理主机转发请求
//_addProxy(client);
//添加证书校验
_verifyCer(client, cerContent);
};
}
//get请求
Future<void> doGet(String url) async {
requestMap[url] = CancelToken(); //取消标志,用于取消请求
Response response = await dio.get(url, cancelToken: requestMap[url]);
String json = response.data.toString();
//...解析json
}
//post请求-请求参数为json
Future<void> doPostByJson(String url, {Map<String, dynamic>? params}) async {
requestMap[url] = CancelToken(); //取消标志,用于取消请求
//1.发起post请求
Response response;
if (params != null) {//有请求参数时
response = await dio.post(url, data: params, cancelToken: requestMap[url]);
} else { //无请求参数时
response = await dio.post(url, cancelToken: requestMap[url]);
}
//2.获取返回数据并解析
String json = response.data.toString();
//...解析json
}
//post请求-请求参数为Form表单,contentType为multipart/form-data
Future<void> doPostByForm(String url, {Map<String, dynamic>? params}) async {
requestMap[url] = CancelToken(); //取消标志,用于取消请求
//1.发起post请求
Response response;
if (params != null) {//有请求参数时,封装请求参数到FormData
FormData formData = FormData.fromMap(params);
response = await dio.post(url, data: formData, cancelToken: requestMap[url]);
} else {
response = await dio.post(url, cancelToken: requestMap[url]);
}
//2.获取返回数据并解析
String json = response.data.toString();
//...解析json
}
//文件上传
Future<void> uploadFile(String url, String filePath, {Map<String, dynamic>? params}) async {
requestMap[url] = CancelToken(); //取消标志,用于取消请求
//1.封装文件与请求参数到FormData
Map<String, dynamic> params1 = {
"file": File(filePath)
//"files": [...] //此字段支持多个文件上传
};
if (params != null) {
params.forEach((key, value) { //遍历Map集合
params1[key] = value; //添加参数到Map集合中
});
}
FormData formData = FormData.fromMap(params1);
//2.发起post请求,上传文件
Response response = await dio.post(url, data: formData, cancelToken: requestMap[url], onSendProgress: (int progress, int total) {
print("文件总长度: $total, 当前上传进度: $progress");
if(progress == total) {
print("文件上传完成");
//...处理上传完后的逻辑
}
});
//3.获取返回数据并解析
String json = response.data.toString();
//...解析json
}
//文件下载
Future<void> downloadFile(String url, String saveFilePath) async {
requestMap[url] = CancelToken(); //取消标志,用于取消请求
try {
//发起post请求,下载文件
Response response = await dio.download(url, saveFilePath, cancelToken: requestMap[url], onReceiveProgress: (int count, int total) {
print("文件总长度: $total, 当前下载进度: $count");
if(count == total) {
print("文件下载完成");
//...处理下载完后的逻辑
}
});
} on DioError catch (e) {
if (e.type == DioErrorType.connectTimeout) {
print("连接超时");
} else if (e.type == DioErrorType.sendTimeout) {
print("请求超时");
} else if (e.type == DioErrorType.receiveTimeout) {
print("接收超时");
} else if (e.type == DioErrorType.response) {
print("响应异常");
} else {
print("下载失败");
}
}
}
//取消请求
Future<void> cancel(String url) async {
if (requestMap[url] != null && !requestMap[url]!.isCancelled) {
requestMap[url]!.cancel();
requestMap[url] = null;
}
}
}
2.使用HttpClient实现:
class HttpClientUtil {
late HttpClient httpClient;
//初始化HttpClient
HttpClient _createHttpClient(Uri uri) {
if (httpClient != null) return httpClient;
httpClient = HttpClient(context: _getSecurityContext()); //创建HttpClient时添加证书
httpClient.idleTimeout = Duration(milliseconds: 10000); //对应请求头keep-alive
httpClient.connectionTimeout = Duration(milliseconds: 10000); //连接超时时间
httpClient.maxConnectionsPerHost = 5; //同一个url,允许同时连接的最大数
httpClient.autoUncompress = true; //对应请求头Content-Encoding,true时使用gzip压缩
//添加Basic认证或Digest认证
//_addAuth(uri);
//添加代理主机,通过代理主机转发请求
//_addProxy(uri);
return httpClient;
}
//添加Basic认证或Digest认证
void _addAuth(Uri uri){
httpClient.addCredentials(uri, "用户角色分组(后台添加)", HttpClientBasicCredentials("用户名", "密码")); //添加Basic认证(Base64编码),对应请求头Authorization,值为:Basic xxx
httpClient.addCredentials(uri, "用户角色分组(后台添加)", HttpClientDigestCredentials("用户名", "密码")); //添加Digest认证(哈希运算),对应请求头Authorization,值为:Basic xxx
}
//添加代理主机,通过代理主机转发请求
void _addProxy(){
httpClient.findProxy = (uri) {
return "PROXY IP:端口"; //代理主机
//return "DIRECT"; //不需要代理主机时返回"DIRECT"
};
//代理主机添加Basic认证或Digest认证
httpClient.addProxyCredentials("代理主机IP", 80, "用户角色分组", HttpClientBasicCredentials("用户名", "密码"));
httpClient.addProxyCredentials("代理主机IP", 80, "用户角色分组", HttpClientDigestCredentials("用户名", "密码"));
}
//添加证书校验
SecurityContext _getSecurityContext() {
//1.1.添加证书,请求时会自动校验
SecurityContext sc = SecurityContext();
//sc.setTrustedCertificates("证书本地路径"); //支持PEM格式(无需密码)、PKCS12格式(需要证书密码)
//1.2.上面添加的证书验证失败时,触发以下监听
httpClient.badCertificateCallback = (X509Certificate cert, String host, int port) {
return true; //不校验证书,全部放行
};
return sc;
}
//添加头字段
void _addHeader(HttpClientRequest request) {
request.headers.add("Connection", "keep-alive");
request.headers.add("Content-Type", "application/json");
}
//执行网络请求
Future<String?> doRequest(String url) async {
Uri uri = Uri.parse(url);
//1.创建一个HttpClient
HttpClient httpClient = _createHttpClient(uri);
try {
//2.0.打开Http连接
HttpClientRequest request = await httpClient.getUrl(uri);
//2.1.POST方式打开Http连接
//HttpClientRequest request = await httpClient.postUrl(uri);
//2.2.GET方式打开Http连接
//HttpClientRequest request = await httpClient.get("www.baidu.com", 80, "/path?key=value");
//3.添加请求头
_addHeader(request);
//4.等待连接服务器(会将请求信息发送给服务器)
HttpClientResponse response = await request.close();
//5.读取返回的json
String json = await response.transform(utf8.decoder).join();
print("json: " + json);
return json;
} catch (e) {
print("e: ${e.toString()}");
return null;
} finally {
//6.关闭client
httpClient.close();
}
}
}
三、TCP/IP长连接:
1.使用WebSocket实现长连接:
(1)添加WebSocket依赖,在pubspec.yaml中:
dependencies:
web_socket_channel: ^2.0.0 #WebSocket库
(2)使用WebSocket实现长连接:
class WebSocketUtil {
late IOWebSocketChannel channel;
//1.创建websocket连接,并监听消息
Future<void> connect(String ws, Map<String, dynamic>? headers) async {
channel = IOWebSocketChannel.connect(ws, headers: headers); //创建websocket连接
channel.stream.listen((msg) { //监听消息
String json = msg;
//...解析json
});
}
//2.发送消息
Future<void> sendMsg(String msg) async {
channel.sink.add(msg); //发送消息
}
//3.关闭连接
Future<void> close() async {
channel.sink.close(); //关闭连接
}
}
2.使用Socket实现长连接:
class SocketUtil {
late var socket;
//1.创建socket连接
Future<void> connect(String host, int port) async {
socket = Socket.connect(host, port); //创建socket连接
}
//2.读取消息
Future<String> readMsg() {
Future<String> msg = utf8.decoder.bind(socket).join(); //读取消息内容
return msg;
}
//3.发送消息
Future<void> sendMsg(String msg) async {
socket.writeln(msg);
socket.flush(); //发送消息
}
//4.关闭连接
Future<void> close() async {
socket.close(); //关闭连接
}
}