前言:
Android开发中网络开发是一个很重要的模块,基本上所有的APP也都用到了这个模块。从最开始自己实现网络模块到后来使用Google提供的网络框架Volley,再到现在很流行的Okhttp和Retrofit。实现网络模块也变得越来越简单,框架帮我们做的也越来越多。我们就从Okhttp开始,来简单聊聊。
Okhttp大家肯定都不会陌生,没吃过猪头也见过猪跑对吧。
聊Okhttp的时候就不得不提到Square,这家公司是美国一家移动支付公司。这家公司在第三方框架方面也有很多不错的作品,比如Okhttp,Retrofit和Picasso都是出自这家公司。
废话不多说,下面直接上代码。
首先需要在build.gradle中加入
implementation'com.squareup.okhttp3:okhttp:3.12.1'
一、get方法
Okhttp为我们提供了同步和异步两种执行方法
同步:
val okHttpClient = OkHttpClient()
val call = Request
.Builder()
.url("请求地址")
.build()
val newCall = okHttpClient.newCall(call)
Thread(Runnable {
try {
val response: Response = newCall.execute()
val body = response.body()
if (response.code() ==200 && body !=null) {
Log.d("Test",body.string())
}else {
Log.d("Test","请求失败")
}
}catch (e: Exception) {
Log.d("Test","报错了:${e.message}")
}
}).start()
同步的时候如果请求过程中报错,是没有Error返回的,需要自己try/catch来捕获异常,因为代码不难,这里就不具体说明了。注:response.code()所返回的参数不是服务器返回的,是框架自己返回的。
异步:
val okHttpClient = OkHttpClient()
val call = Request
.Builder()
.url("请求地址")
.build()
val newCall = okHttpClient.newCall(call)
newCall.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.d("Test","请求报错: ${e.message}")
}
override fun onResponse(call: Call, response: Response) {
val body = response.body()
if (response.code() ==200 && body !=null) {
Log.d("Test",body.string())
}else {
Log.d("Test","请求失败")
}
}
})
异步newCall 调用的是enqueue而不是execute,传入了一个接口来接收返回数据。这里需要注意的是onFailure和onResponse是在子线程中而不是主线程。Okhttp的异步其实也是在内部使用线程来实现的。
二、Post方法
Post方法在调用上和get方法没有太大区别,它需要多调用一个post方法。
在post方法中,我们会传入RequestBody这个对象。那么我们看看这个对象。
我们可以看到这个对象可以用自带的create方法来new一个对象然后传入。我们进入RequestBody看看他的源码。
我们可以发现它是一个abstract类,并且有FormBody和MultipartBody两个实现类。以下我们将展示这三个类的具体用法。
1.RquestBody:
在调用RequestBody的create方法的时候需要传入一个MediaType。这里的MediaType是用来描述HTTP请求或响应体的内容类型。常见的媒体格式类型有:
text/html:HTML格式
text/pain:纯文本格式
image/jpeg:jpg图片格式
application/json:JSON数据格式
application/octet-stream:二进制流数据(如文件下载)
application/x-www-form-urlencoded:form表单encType属性的默认格式,表单数据将以key/value的形式发送到服务端
multipart/form-data:表单上传文件的格式
val okHttpClient = OkHttpClient()
val mediaType = MediaType.parse("application/json; charset=utf-8")
val json = JSONObject()
json.put("key","content")
val requestBody = RequestBody.create(mediaType, json.toString())
val request = Request
.Builder()
.url("请求地址")
.post(requestBody)
.build()
val newCall = okHttpClient.newCall(request)
newCall.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.d("Test","请求报错: ${e.message}")
}
override fun onResponse(call: Call, response: Response) {
val body = response.body()
if (response.code() ==200 && body !=null) {
Log.d("Test",body.string())
}else {
Log.d("Test","请求失败")
}
}
})
Post这里用的是异步请求的方法,同步的方法和get的同步方法一样。这里的post()方法如果没有调用,则默认是使用get去请求。这里上传的数据为json,大家可以根据自己需求去改变MediaType。
2.FormBody
FormBody一般用户表单请求。
val okHttpClient = OkHttpClient()
val requestBody = FormBody
.Builder()
.add("key","content")
.build()
val request = Request
.Builder()
.url("请求地址")
.post(requestBody)
.build()
val newCall = okHttpClient.newCall(request)
newCall.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.d("Test","请求报错: ${e.message}")
}
override fun onResponse(call: Call, response: Response) {
val body = response.body()
if (response.code() ==200 && body !=null) {
Log.d("Test",body.string())
}else {
Log.d("Test","请求失败")
}
}
})
FormBody的用法和RequestBody的用法差不多,这里就不过多描述了。
3.MultipartBody
MultipartBody可以同时上传多种类型的数据。
val okHttpClient = OkHttpClient()
val file = File("文件地址")
val mediaType = MediaType.parse("application/octet-stream")
val fileBody = RequestBody.create(mediaType, file)
val requestBody = MultipartBody
.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("key","content")
.addFormDataPart("key", file.name, fileBody)
.build()
val request = Request
.Builder()
.url("请求地址")
.post(requestBody)
.build()
val newCall = okHttpClient.newCall(request)
newCall.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.d("Test","请求报错: ${e.message}")
}
override fun onResponse(call: Call, response: Response) {
val body = response.body()
if (response.code() ==200 && body !=null) {
Log.d("Test",body.string())
}else {
Log.d("Test","请求失败")
}
}
})
上面的代码难度不大,大家应该都能看懂,MultipartBody某种意义上更像RequestBody和FormBody的结合。到这里Post的方法也讲得差不多了。
这是我第一次写文章,肯定有很多不完善的地方,希望大家提出来,以后改进!!!
最后要过年了,祝大家新年快乐,越来越有钱!!!