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

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

OkHttp的介绍


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

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

添加依赖


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

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

OkHttp的使用

记得添加权限!

<uses-permission android:name="android.permission.INTERNET" />

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()
            }
        }
    }

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之间就是成功的。

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()
            }
        }
    }

3.自定义缓存


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

Cache(缓存文件地址,缓存最大容量字节)

val okHttpClient:OkHttpClient=OkHttpClient.Builder()
        .cache(Cache(File(externalCacheDir,"a"),1024*1024))
         .build()

4. 自定义Cookie


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

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

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

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

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

目录
相关文章
|
4月前
|
机器学习/深度学习 算法 量子技术
GQNN框架:让Python开发者轻松构建量子神经网络
为降低量子神经网络的研发门槛并提升其实用性,本文介绍一个名为GQNN(Generalized Quantum Neural Network)的Python开发框架。
110 4
GQNN框架:让Python开发者轻松构建量子神经网络
|
2月前
|
机器学习/深度学习 算法 PyTorch
【Pytorch框架搭建神经网络】基于DQN算法、优先级采样的DQN算法、DQN + 人工势场的避障控制研究(Python代码实现)
【Pytorch框架搭建神经网络】基于DQN算法、优先级采样的DQN算法、DQN + 人工势场的避障控制研究(Python代码实现)
|
2月前
|
监控 前端开发 安全
Netty 高性能网络编程框架技术详解与实践指南
本文档全面介绍 Netty 高性能网络编程框架的核心概念、架构设计和实践应用。作为 Java 领域最优秀的 NIO 框架之一,Netty 提供了异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。本文将深入探讨其 Reactor 模型、ChannelPipeline、编解码器、内存管理等核心机制,帮助开发者构建高性能的网络应用系统。
226 0
|
2月前
|
机器学习/深度学习 算法 PyTorch
【DQN实现避障控制】使用Pytorch框架搭建神经网络,基于DQN算法、优先级采样的DQN算法、DQN + 人工势场实现避障控制研究(Matlab、Python实现)
【DQN实现避障控制】使用Pytorch框架搭建神经网络,基于DQN算法、优先级采样的DQN算法、DQN + 人工势场实现避障控制研究(Matlab、Python实现)
140 0
|
5月前
|
机器学习/深度学习 API TensorFlow
BayesFlow:基于神经网络的摊销贝叶斯推断框架
BayesFlow 是一个基于 Python 的开源框架,利用摊销神经网络加速贝叶斯推断,解决传统方法计算复杂度高的问题。它通过训练神经网络学习从数据到参数的映射,实现毫秒级实时推断。核心组件包括摘要网络、后验网络和似然网络,支持摊销后验估计、模型比较及错误检测等功能。适用于流行病学、神经科学、地震学等领域,为仿真驱动的科研与工程提供高效解决方案。其模块化设计兼顾易用性与灵活性,推动贝叶斯推断从理论走向实践。
187 7
BayesFlow:基于神经网络的摊销贝叶斯推断框架
|
5月前
|
安全 Java Android开发
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
267 0
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
|
6月前
|
Java Android开发
Android使用okhttp加载图片
本教程介绍了如何使用 OkHttp 和 Handler 在 Android 应用中加载并显示网络图片。首先确保添加了网络权限和 OkHttp、Okio 的依赖包。通过定义全局 Handler 处理消息,实例化 OkHttpClient 请求图片数据,并在 onResponse 方法中将图片数据传递给主线程,最终利用 Bitmap 加载到 ImageView 中。
141 4
|
8月前
|
API 数据处理 Android开发
Android网络请求演变:从Retrofit到Flow的转变过程。
通过这个比喻,我们解释了 Android 网络请求从 Retrofit 到 Flow 的转变过程。这不仅是技术升级的体现,更是反映出开发者在面对并发编程问题时,持续探索和迭求更好地解决方案的精神。未来,还会有更多新的技术和工具出现,我们期待一同 witness 这一切的发展。
257 36
|
6月前
|
Web App开发 缓存 JavaScript
Android网络小说阅读器的实现
小说阅读Demo,。此Demo使用Jsoup解析HTML,实现小说数据抓取(数据源自网络),并包含自定义View、六章小说缓存等功能,但未实现下载。项目还包括屏幕适配、字体设置等,借助第三方框架完成优化。以下是主页、详情页、阅读页等界面展示。
164 0
|
8月前
|
XML JavaScript Android开发
【Android】网络技术知识总结之WebView,HttpURLConnection,OKHttp,XML的pull解析方式
本文总结了Android中几种常用的网络技术,包括WebView、HttpURLConnection、OKHttp和XML的Pull解析方式。每种技术都有其独特的特点和适用场景。理解并熟练运用这些技术,可以帮助开发者构建高效、可靠的网络应用程序。通过示例代码和详细解释,本文为开发者提供了实用的参考和指导。
285 15
下一篇
oss云网关配置