[Android]网络框架之OkHttp(详细)(kotlin)

目录

OkHttp的介绍

添加依赖

OkHttp的使用

get的同步与异步请求

post的同步与异步请求

POST请求的数据格式

POST请求上传文件

POST请求上传json对象

POST请求上传多个数据

OkHttp的配置

1.Builder构建器

2.自定义拦截器

3.自定义缓存

4. 自定义Cookie


OkHttp的介绍


https://square.github.io/okhttp/

由Square公司贡献的一个处理网络请求的开源项目,是目前Android使用最广泛的网络框架。从Android4.0开始HttpURLConnection的底层实现采用的是OkHttp

添加依赖


 implementation 'com.squareup.okhttp3:okhttp:4.9.0'

上述依赖会自动下载okhttp库和okio库 

OkHttp的使用

 记得添加权限!

get的同步与异步请求


get请求的基本步骤:

1.创建OkHttpClient的实例

2.创建Request对象,设置url地址

3.创建Call对象,调用它的execute方法(同步)或者enqueue方法(异步)来发送请求并获取服务器返回的数据

4.得到服务器返回的数据的具体内容

get同步请求 

//get同步请求
    fun getSync() {
        thread {
            try {
                val client = OkHttpClient()
                val request = Request.Builder()
                    .url("https://www.httpbin.org/get?a=1&b=2")
                    .build()
                val call=client.newCall(request)
                val response = call.execute()//execute方法会阻塞在这里,必须等到服务器响应,得到response才会执行下面的代码
                val requestData = response.body?.string()
                if (requestData != null) {
                    Log.e("getSync", requestData)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

[Android]网络框架之OkHttp(详细)(kotlin)_第1张图片

get异步请求 

//get异步请求
    fun getAsync(){
        val client = OkHttpClient()
        val request = Request.Builder()
            .url("https://www.httpbin.org/get?a=1&b=2")
            .build()
        val call=client.newCall(request)
        //异步请求,enqueue方法不会阻塞后续代码的执行
        call.enqueue(object :Callback{
            //请求失败调用
            override fun onFailure(call: Call, e: IOException) {

            }
            //请求结束调用(意味着与服务器的通信成功)
            override fun onResponse(call: Call, response: Response) {
                if(response.isSuccessful){
                    response.body?.let { Log.e("getAsync", it.string()) }
                }
            }
        })

    }

 响应码在200到299之间就是成功的。

 [Android]网络框架之OkHttp(详细)(kotlin)_第2张图片

post的同步与异步请求


post请求的基本步骤:

1.创建OkHttpClient的实例

2.创建RequestBody对象来存放待提交的参数

2.创建Request对象,设置url地址,调用post方法,把RequestBody对象传入

3.创建Call对象,调用它的execute方法(同步)或者enqueue方法(异步)来发送请求并获取服务器返回的数据

4.得到服务器返回的数据的具体内容

post同步请求提交键值对

 //post同步请求
    fun postSync(){
        thread {
            try {
                val client = OkHttpClient()
                val requestBody=FormBody.Builder().add("a","1").add("b","2").build()
                val request = Request.Builder()
                    .url("https://www.httpbin.org/post")
                    .post(requestBody)
                    .build()
                val call=client.newCall(request)
                val response = call.execute()//execute方法会阻塞在这里,必须等到服务器响应,得到response才会执行下面的代码
                val requestData = response.body?.string()
                if (requestData != null) {
                    Log.e("postSync", requestData)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

post异步请求提交键值对

//post异步请求
    fun postAsync(){
        val client = OkHttpClient()
        val requestBody=FormBody.Builder().add("a","1").add("b","2").build()
        val request = Request.Builder()
            .url("https://www.httpbin.org/post")
            .post(requestBody)
            .build()
        val call=client.newCall(request)
        //异步请求,enqueue方法不会阻塞后续代码的执行
        call.enqueue(object :Callback{
            //请求失败调用
            override fun onFailure(call: Call, e: IOException) {

            }
            //请求结束调用(意味着与服务器的通信成功,)
            override fun onResponse(call: Call, response: Response) {
                if(response.isSuccessful){
                    response.body?.let { Log.e("postAsync", it.string()) }
                }
            }
        })
    }

POST请求的数据格式


协议规定POST提交的数据必须放在请求体中,但协议并没有规定数据必须使用什么编码方式。而常用的数据编码方式有:

  • application/x-www-form-urlencoded:默认, key1=value1&key2=value2
  • multipart/form-data:一般用于表单需要文件上传
  • .application/json:提交json数据
  • text/plain:将文件设置为纯文本的形式
  • application/octet-stream:提交二进制数据,如果用于文件上传,只能上传一个文件

注意:

 String、ByteArray、ByteString转RequestBody都用toRequestBody()

而File转RequestBody用asRequestBody()

POST请求上传文件


fun Filetest(){
        thread {
            try {
                val client = OkHttpClient()
                //创建文件
                val file1=File(externalCacheDir,"jfApp")
                if (!file1.exists()){
                    file1.createNewFile();
                }
                //在file1中写入aaa
                file1.printWriter().use { out->
                    out.println("aaa")
                }
                //把file转化为RequestBody
                val fileBody1=file1.asRequestBody("text/plain".toMediaType())
                val request = Request.Builder()
                    .url("https://www.httpbin.org/post")
                    .post(fileBody1)
                    .build()
                val call=client.newCall(request)
                val response = call.execute()
                val requestData = response.body?.string()
                if (requestData != null) {
                    Log.e("file", requestData)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

POST请求上传json对象


fun jsontest(){
        thread {
            try {
                val client = OkHttpClient()
                val json:String="{\"a\":1,\"b\":2}"
                val requestBody=json.toRequestBody("application/json".toMediaType())
                val request = Request.Builder()
                    .url("https://www.httpbin.org/post")
                    .post(requestBody)
                    .build()
                val call=client.newCall(request)
                val response = call.execute()
                val requestData = response.body?.string()
                if (requestData != null) {
                    Log.e("jsontext", requestData)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

POST请求上传多个数据


fun Filetest(){
        thread {
            try {
                val client = OkHttpClient()
                //创建文件
                val file1=File(externalCacheDir,"jfApp")
                val file2=File(externalCacheDir,"jfApp2")
                if (!file1.exists()){
                    file1.createNewFile();
                }
                if (!file2.exists()){
                    file2.createNewFile();
                }
                //在file1中写入aaa
                file1.printWriter().use { out->
                    out.println("aaa")
                }
                //把file转化为RequestBody
                val fileBody1=file1.asRequestBody("text/plain".toMediaType())
                val fileBody2=file2.asRequestBody("text/plain".toMediaType())
                //把数据放入multipartBody中
                val multipartBody = MultipartBody.Builder()
                    .addFormDataPart("file1", file1.name,fileBody1)//添加文件
                    .addFormDataPart("file2",file2.name,fileBody2)
                     .addFormDataPart("a","1")//添加键值对
                    .build()
                val request = Request.Builder()
                    .url("https://www.httpbin.org/post")
                    .post(multipartBody)
                    .build()
                val call=client.newCall(request)
                val response = call.execute()
                val requestData = response.body?.string()
                if (requestData != null) {
                    Log.e("file", requestData)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

OkHttp的配置

1.Builder构建器


val okHttpClient:OkHttpClient=OkHttpClient.Builder().build()

可以加入一些自己配置的小配件

2.自定义拦截器


okhttp的拦截器就是在intercept(chain: Interceptor.Chain)的回调中对Request和Response进行修改,然后通过chain.proceed(request)调起下一个拦截器。

val okHttpClient:OkHttpClient=OkHttpClient.Builder().addInterceptor(xxx).build()

val okHttpClient:OkHttpClient=OkHttpClient.Builder().addNetworkInterceptor(xxx).build()

addInterceptor()和addNetworkInterceptor()的区别:

1.addInterceptor()的优先级高于addNetworkInterceptor()。

2.在1的条件下,添加拦截器的的顺序就是执行的顺序。

在拦截器中修改Request添加请求头,就可以在每个Request对象中自动添加请求头,减少麻烦。

fun interceptor(){
        thread {
            try {
                val okHttpClient:OkHttpClient=OkHttpClient.Builder()
                    .addInterceptor(object : Interceptor{
                        override fun intercept(chain: Interceptor.Chain): Response {
                            //前置处理
                            val request=chain.request().newBuilder()
                                .addHeader("os","android")
                                .addHeader("version","1.0").build()
                            val response=chain.proceed(request)
                            //后置处理
                            return  response
                        }
                    })
                    .build()
                val request = Request.Builder()
                    .url("https://www.httpbin.org/get?a=1&b=2")
                    .build()
                val call=okHttpClient.newCall(request)
                val response = call.execute()//execute方法会阻塞在这里,必须等到服务器响应,得到response才会执行下面的代码
                val requestData = response.body?.string()
                if (requestData != null) {
                    Log.e("getSync", requestData)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

    }

[Android]网络框架之OkHttp(详细)(kotlin)_第3张图片

3.自定义缓存


OkHttp按照Http协议规则实现了缓存的处理,缓存是比如:当我们发起第一次请求之后,如果后续还需要进行同样的请求,此时如果符合缓存规则,则可以减少与服务器的网络通信,直接从本地文件缓存中读取响应放回给请求者。但是在默认情况下,OkHttp的缓存是关闭状态,需要我们开启。

Cache(缓存文件地址,缓存最大容量字节)
 val okHttpClient:OkHttpClient=OkHttpClient.Builder()
        .cache(Cache(File(externalCacheDir,"a"),1024*1024))
         .build()
                    

4. 自定义Cookie


 Cookie是某个网站为了辨别用户身份,进行会话跟踪(比如确定登录状态)而存储在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息。

[Android]网络框架之OkHttp(详细)(kotlin)_第4张图片

我们在玩Android - wanandroid.com - 每日推荐优质文章

这个网站上注册账号,然后得到账号和密码。这个网站提供很多接口。

请求登录接口之后将返回cookie保存下来,才能请求其他接口,这里请求的是收藏列表。

fun cookietest(){
         val cookies = HashMap>()
          thread {
              val okHttpClient:OkHttpClient=OkHttpClient.Builder().cookieJar(object :CookieJar{       //加载并保存cookie
                  override fun loadForRequest(url: HttpUrl): List {
                      val cookies: List? = cookies.get(url.host)
                      if(cookies==null)
                          return ArrayList()
                      else {
                          return cookies
                      }
                  }
                  //保存cookie
                  override fun saveFromResponse(url: HttpUrl, list: List) {
                      cookies.put(url.host,list)
                  }

              }).build()
              val fromBody=FormBody.Builder().add("username","xxx")
                  .add("password","xxx").build()//网站的账号和密码
              var request = Request.Builder()
                  .url("https://www.wanandroid.com/user/login")
                  .post(fromBody)
                  .build()
              var call=okHttpClient.newCall(request)
            try {

                val response = call.execute()
                val requestData = response.body?.string()
                if (requestData != null) {
                    Log.e("cookietest", requestData)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
              request=Request.Builder().url("https://www.wanandroid.com/lg/collect/list/0/json")
                  .build()
              call=okHttpClient.newCall(request)
              try {
                  val Response=call.execute()
                  Response.body?.let { Log.e("cookietest", it.string()) }
              }catch (e:Exception){
                  e.printStackTrace()
              }
        }
    }

你可能感兴趣的:(Android,android,okhttp,kotlin)