一、本地文件操作:
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(); //关闭连接
- }
- }