尾声
你不踏出去一步,永远不知道自己潜力有多大,千万别被这个社会套在我们身上的枷锁给捆住了,30岁我不怕,35岁我一样不怕,去做自己想做的事,为自己拼一把吧!不试试怎么知道你不行呢?
改变人生,没有什么捷径可言,这条路需要自己亲自去走一走,只有深入思考,不断反思总结,保持学习的热情,一步一步构建自己完整的知识体系,才是最终的制胜之道,也是程序员应该承担的使命。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
======================
1、支持常用的Http操作,比如get,post等
2、异步操作,在io.dart中有相关描述
-
This library allows you to work with files, directories,
-
sockets, processes, HTTP servers and clients, and more.
-
Many operations related to input and output are asynchronous
-
and are handled using [Future]s or [Stream]s, both of which
-
are defined in the [dart:async
-
library](…/dart-async/dart-async-library.html).
-
To use the dart:io library in your code:
import ‘dart:io’;
3、网络调用通常遵循如下步骤:
创建 client. 构造 Uri. 发起请求, 等待请求,同时您也可以配置请求headers、 body。 关闭请求, 等待响应. 解码响应的内容. 4、示例,(httpbin.org 这个网站能测试 HTTP 请求和响应的各种信息,比如 cookie、ip、headers 和登录验证等,且支持 GET、POST 等多种方法)
_httpTest() async {
var url = ‘https://httpbin.org/ip’;
var httpClient = new HttpClient();
String result;
try {
var request = await httpClient.getUrl(Uri.parse(url));
var response = await request.close();
if (response.statusCode == HttpStatus.ok) {
var json = await response.transform(utf8.decoder).join();
var data = jsonDecode(json);
result = data[‘origin’];
print(result);
} else {
result =
‘Error getting IP address:\nHttp status ${response.statusCode}’;
}
} catch (exception) {
result = ‘Failed getting IP address’;
}
}
输出结果:122.70.159.214
二、dio
dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时、自定义适配器等
1、安装
dependencies:
dio: ^3.0.10
2、常用请求
以下实验基于Charles的MapLocal,json文件内容为{“animal”:“dog”}
- get
Response response;
Dio dio = _dio();
response = await dio.get(“http://test?id=1&name=dio1&method=get”);
// 请求参数也可以通过对象传递,上面的代码等同于:
response = await dio.get(“http://test”, queryParameters: {“id”: 2, “name”: “dio2”});
print(response.data[‘animal’]);
- post
Response response;
Dio dio = _dio();
response = await dio.post(“http://test?id=1&name=dio1&method=post”);
// 请求参数也可以通过对象传递,上面的代码等同于:
response = await dio.post(“http://test”, queryParameters: {“id”: 2, “name”: “dio2”});
print(response.data[‘animal’]);
//监听接收数据进度
response = await dio.post(
“http://test”,
queryParameters: {“id”: 2, “name”: “dio2”},
onReceiveProgress: (int receive, int total) {
print(“$receive $total”);
},
);
- 发起多个请求
Dio dio = _dio();
Future.wait([dio.post(“http://test/test1”), dio.get(“http://test/test2”)]).then((e) {
print(e);
}).catchError((e) {});
结果为[{“animal”:“dog”}, {“animal”:“dog”}]
- 下载文件
Dio dio = _dio();
Response response =
await dio.download(“https://www.baidu.com/”, “assets/data/test.html”);
- 上传文件
Response response;
Dio dio = _dio();
FormData formData;
formData = FormData.fromMap({
“animal”: “dog”,
});
response = await dio.post(“http/test/upload”, data: formData);
//上传多个文件
formData = FormData.fromMap({
“animal”: “dog”,
“files”: [
await MultipartFile.fromFile(“assets/data/test1.json”, filename: “test1.json”),
await MultipartFile.fromFile(“assets/data/test2.json”, filename: “test2.json”),
]
});
response = await dio.post(“http/test/upload”, data: formData);
3、配置dio
Dio dio = Dio();
// 你可以使用默认配置或传递一个可选 BaseOptions参数来创建一个Dio实例 :
// 配置dio实例
dio.options.baseUrl = “https://www.xx.com/api”;
dio.options.connectTimeout = 5000; //5s
dio.options.receiveTimeout = 3000;
// 或者通过传递一个 options
来创建dio实例
BaseOptions options = BaseOptions(
baseUrl: “https://www.xx.com/api”,
connectTimeout: 5000,
receiveTimeout: 3000,
);
dio = Dio(options);
4、请求配置
BaseOptions描述的是Dio实例发起网络请求的的公共配置,而Options类描述了每一个Http请求的配置信息,每一次请求都可以单独配置,单次请求的Options中的配置信息可以覆盖BaseOptions中的配置,下面是BaseOptions的配置项:
{
/// Http method.
String method;
/// 请求基地址,可以包含子路径,如: “https://www.google.com/api/”.
String baseUrl;
/// Http请求头.
Map<String, dynamic> headers;
/// 连接服务器超时时间,单位是毫秒.
int connectTimeout;
/// 2.x中为接收数据的最长时限.
int receiveTimeout;
/// 请求路径,如果 path
以 "http(s)"开始, 则 baseURL
会被忽略; 否则,
/// 将会和baseUrl拼接出完整的的url.
String path = “”;
/// 请求的Content-Type,默认值是"application/json; charset=utf-8".
/// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,
/// 可以设置此选项为 Headers.formUrlEncodedContentType
, 这样[Dio]
/// 就会自动编码请求体.
String contentType;
/// [responseType] 表示期望以那种格式(方式)接受响应数据。
/// 目前 [ResponseType] 接受三种类型 JSON
, STREAM
, PLAIN
.
///
/// 默认值是 JSON
, 当响应头中content-type为"application/json"时,dio 会自动将响应内容转化为json对象。
/// 如果想以二进制方式接受响应数据,如下载一个二进制文件,那么可以使用 STREAM
.
///
/// 如果想以文本(字符串)格式接收响应数据,请使用 PLAIN
.
ResponseType responseType;
/// validateStatus
决定http响应状态码是否被dio视为请求成功, 返回validateStatus
/// 返回true
, 请求结果就会按成功处理,否则会按失败处理.
ValidateStatus validateStatus;
/// 用户自定义字段,可以在 [Interceptor]、[Transformer] 和 [Response] 中取到.
Map<String, dynamic> extra;
/// Common query parameters
Map<String, dynamic /String|Iterable/ > queryParameters;
}
5、响应数据
当请求成功时会返回一个Response对象,它包含如下字段:
{
/// 响应数据,可能已经被转换了类型, 详情请参考Options中的[ResponseType].
T data;
/// 响应头
Headers headers;
/// 本次请求信息
Options request;
/// Http status code.
int statusCode;
/// 是否重定向(Flutter Web不可用)
bool isRedirect;
/// 重定向信息(Flutter Web不可用)
List redirects ;
/// 真正请求的url(重定向最终的uri)
Uri realUri;
/// 响应对象的自定义字段(可以在拦截器中设置它),调用方可以在then
中获取.
Map<String, dynamic> extra;
}
6、拦截器
我们可以通过继承Interceptor来实现自定义的拦截器
每个 Dio 实例都可以添加任意多个拦截器,他们组成一个队列,拦截器队列的执行顺序是FIFO。通过拦截器你可以在请求之前或响应之后(但还没有被 then 或 catchError处理)做一些统一的预处理操作。
dio.interceptors.add(InterceptorsWrapper(
onRequest:(RequestOptions options) async {
// 在请求被发送之前做一些事情
return options; //continue
// 如果你想完成请求并返回一些自定义数据,可以返回一个Response
对象或返回dio.resolve(data)
。
// 这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义数据data.
//
// 如果你想终止请求并触发一个错误,你可以返回一个DioError
对象,或返回dio.reject(errMsg)
,
// 这样请求将被中止并触发异常,上层catchError会被调用。
},
onResponse:(Response response) async {
// 在返回响应数据之前做一些预处理
return response; // continue
},
onError: (DioError e) async {
// 当请求失败时做一些预处理
return e;//continue
}
));
7、拦截器中可以进行其他异步操作
dio.interceptors.add(InterceptorsWrapper(
onRequest:(Options options) async{
//…If no token, request token firstly.
Response response = await dio.get(“/token”);
//Set the token to headers
options.headers[“token”] = response.data[“data”][“token”];
return options; //continue
}
));
8、Lock/unlock拦截器
你可以通过调用拦截器的 lock()/unlock 方法来锁定/解锁拦截器。一旦请求/响应拦截器被锁定,接下来的请求/响应将会在进入请求/响应拦截器之前排队等待,直到解锁后,这些入队的请求才会继续执行(进入拦截器)。这在一些需要串行化请求/响应的场景中非常实用,后面我们将给出一个示例。
tokenDio = Dio(); //Create a instance to request the token.
tokenDio.options = dio.options;
dio.interceptors.add(InterceptorsWrapper(
onRequest:(Options options) async {
// If no token, request token firstly and lock this interceptor
// to prevent other request enter this interceptor.
dio.interceptors.requestLock.lock();
// We use a Dio(to avoid dead lock) instance to request token.
Response response = await tokenDio.get(“/token”);
//Set the token to headers
options.headers[“token”] = response.data[“data”][“token”];
dio.interceptors.requestLock.unlock();
return options; //continue
}
));
假设这么一个场景:我们需要给每个请求头中设置token,如果token不存在我们需要先请求token,获取到再继续请求,由于请求token过程是异步的,所以我们需要先锁定拦截器防止其他请求在没有获取到token的情况下进行网络请求,获取到token再解锁
9、clear()方法来清空等待队列
dio.interceptors.clear()
10、日志(开启后会打印request和response相关信息)
//由于拦截器队列的执行顺序是FIFO,如果把log拦截器添加到了最前面,则后面拦截器对options的更改就不会被打印(但依然会生效), 所以建议把log拦截添加到队尾。
dio.interceptors.add(LogInterceptor(responseBody: false)); //开启请求日志
11、DioError
{
/// Request info.
RequestOptions request;
/// Response info, it may be null
if the request can’t reach to
/// the http server, for example, occurring a dns error, network is not available.
Response response;
/// 错误类型,见下文
DioErrorType type;
///原始的error或exception对象,通常type为DEFAULT时存在。
dynamic error;
}
enum DioErrorType {
/// It occurs when url is opened timeout.
CONNECT_TIMEOUT,
/// It occurs when url is sent timeout.
SEND_TIMEOUT,
///It occurs when receiving timeout.
RECEIVE_TIMEOUT,
/// When the server response, but with a incorrect status, such as 404, 503…
RESPONSE,
/// When the request is cancelled, dio will throw a error with this type.
CANCEL,
/// Default error type, Some other Error. In this case, you can
/// read the DioError.error if it is not null.
DEFAULT
}
12、CancelToken,取消请求
CancelToken token = CancelToken();
dio.post(“/testpost?id=1&name=dio1&method=post”,cancelToken: token).catchError((e) {
//我们会发现CancelToken提供了错误类型的判断,即此时CancelToken.isCancel(err)是true
//如
if (CancelToken.isCancel(err)) {
print(“被取消啦”);
}
}).then((data) {
return data;
});
token.cancel();
cancel_token.dart中源码也是判断DioErrorType
尾声
以薪资待遇为基础,以发展为最终目标,要在高薪资的地方,谋求最好的发展!
下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
cancel_token.dart中源码也是判断DioErrorType
尾声
以薪资待遇为基础,以发展为最终目标,要在高薪资的地方,谋求最好的发展!
下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。
[外链图片转存中…(img-LxlkD4Dp-1714998961634)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!