OkHttp简单实践 | 青训营笔记

116 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第5天.

OkHttp介绍

OkHttp是一个轻量级的开源网络库,用来处理HTTP网络请求。被很多的Android App作为网络处理的选项。
在OkHttp出现以前,也有Android自带的HttpURLConnection,不过对比这个实在是繁琐,还得自己构建异步请求。

简单使用

首先把OkHttp加入项目的Gradle依赖,往build.gradle的dependencies里加入一行

implementation 'com.squareup.okhttp:okhttp:2.7.5'

后面的版本号可以改成最新的版本。
OkHttp的基本使用如下

val client : OkHttpClient = OkHttpClient.Builder().
                            connectTimeout(30,TimeUnit.SECONDS).build()
val request = Request.Builder().url(targetURL).get().build()
val call : Call = OkHttpClient().newCall(request)

首先,先创建了一个OkHttpClient。这路通过Builder的形式创建,设置了链接超时时间为30秒,除此之外,还可以设置代理,缓存策略,添加拦截器等。
再构建了一个Request,设置请求方法为get,设置请求的URL地址。
对于Post请求,只需要如下改动

val formBody : FormBody = FormBody.Builder().add("Key","Value").add("head","stirng")  
request = Request.Builder().url(targetURL).post(formBody).build()

最后把这个Request封装为一个Call。
接着来进行请求操作

call.enqueue(object : Callback{
                override fun onFailure(call: Call, e: IOException) {
                    Log.e("HTTP","Fail when making call")
                    e.printStackTrace()
                }

                override fun onResponse(call: Call, response: Response) {  
                    //Do Something
                }

call.enqueue代表着进行一个异步请求。这个方法需要传入一个CallBack接口的实现。当请求成功,会调用接口的onResponse,反之,调用onFailure。
如果想要调用同步请求,那么把enqueue换成excute就可以了。

简单实践——制作一个网图显示器

成品效果


在一个TextEdit里输入一张图片的网址,再按下按钮,就能把图片显示在下面了。
就比如演示里那个Projection Matrix,这是我目前唯一能找到的图片了
图片地址s2.loli.net/2022/08/05/…

制作

新建一个MainActivity,再来个Layout。
Layout的样式随意,反正一个输入框,一个按钮,一个图片显示器
这次由于需要联网,所以先得到manifest里添加联网权限。

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

如果不添加的话会直接报错闪退的hhh
在MainActivity里构造一个MainActivityBinding,并且拿到一系列的控件

var binding: ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater)
val button = binding.button
val textEdit = binding.textEdit  
val imageViewer = binding.imageViewer

对这个Button添加点击事件。

binding.button.setOnClickListener{
            val client : OkHttpClient = OkHttpClient.Builder().connectTimeout(30,TimeUnit.SECONDS).build()
            val str = binding.editText.text.toString()
            var request : Request
            request = Request.Builder().url(str).get().build()
            val call : Call = OkHttpClient().newCall(request)
            call.enqueue(object : Callback{
                override fun onFailure(call: Call, e: IOException) {
                    Log.e("HTTP","Fail when making call")
                    e.printStackTrace()
                }
                override fun onResponse(call: Call, response: Response) {
                    val mStream : InputStream? = response.body()?.byteStream()
                    if(bitmap != null){
                        val bitmap = BitmapFactory.decodeStream(mStream)
                        runOnUiThread {
                            binding.imageView.setImageBitmap(bitmap)
                            }
                        }
                }

            })
        }

逻辑非常简单,就是构建了一个请求,然后异步请求了图片资源,把图片资源转换成了输入二进制流,然后利用BitmapFactory构造了一个图片。
当然,如果只是想拿到请求体的内容并且显示在某个TextView上,也可以使用

val str = response.body().string() 

通过这个语句就能获取到网页的HTML内容或者Json。
但是注意,这里一定要使用 runOnUiThread来更新视图,enqueue事实上是利用了多线程异步,而UI只能在主线程更新。