Kotlin语言写的 OkHttp再次封装成 OkHttpUtils工具 成为超简单的调用

OkHttp再次封装成 OkHttpUtils工具 超简单的调用 Kotlin语言写的
使用的包有:

// 网络请求框架 https://github.com/square/okhttp
implementation 'com.squareup.okhttp3:okhttp:4.1.0’
// i/0 流处理 https://github.com/square/okio
implementation 'com.squareup.okio:okio:2.3.0’
注:自定义委托实现单例使用的是 https://blog.csdn.net/Jeff_YaoJie/article/details/79229071 第三种,Kotlin库提供了几个接口,我们自己的委托必须要实现的几个接口,自定义单例模式,创建一个DelegatesExt.kt文件

使用方法:
  1. 先初始化
    OkHttpUtils(context)
  2. 直接使用 mOkHttpUtils.{你想要使用的get 、 post 或 文件上传方法 }
    如:
    var strJson = mOkHttpUtils.get_Sync("http://t.weather.sojson.com/api/weather/city/101030100")
OkHttpUtils 工具包源码如下:
package com.jeff.mylibrary.utils

import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import com.yzb.lbtafxapp.FileKt.DelegatesExt
import com.yzb.lbtafxapp.FileKt.LogUtils
import okhttp3.*
import java.util.concurrent.TimeUnit;
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okio.*
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import kotlin.collections.HashMap


/**
 * author : Jeff  5899859876@qq.com
 * Csdn :https://blog.csdn.net/Jeff_YaoJie
 * Github: https://github.com/Jay-YaoJie
 * Created :  2019-08-17.
 * description : OkHttp再次封装 借鉴https://github.com/zskingking/OkHttpUtils
 *
 *   implementation 'com.squareup.okhttp3:okhttp:4.1.0' //  //网络请求框架 https://github.com/square/okhttp
 *   implementation 'com.squareup.okio:okio:2.3.0' //i/0 流处理 https://github.com/square/okio
 * 使用方式:
 * 1. 先初始化 OkHttpUtils(context)
 * 2. 直接使用 mOkHttpUtils.{你想要使用的get 、 post 或 文件上传方法 }
 *       如 var strJson = mOkHttpUtils.get_Sync("http://t.weather.sojson.com/api/weather/city/101030100")

 *
 * OkHttp再次封装 https://github.com/zskingking/OkHttpUtils
 *  * 1.OkhttpClient为网络请求的一个中心,它会管理连接池、缓存、SocketFactory、代理
 *   、各种超时时间、DNS、请求执行结果的分发等许多内容。
 * 2.Request:Request是一个HTTP请求体,比如请求方法GET/POST、URL、Header、Body
 *   请求的换粗策略等。
 * 3.Call:通过OkhttpClient和Request来创建Call,Call是一个Task,它会执行网络请求
 *   并且获得响应。这个Task可以通过execute()同步执行,阻塞至请求成功。也可以通过
 *   enqueue()异步执行,会将Call放入一个异步执行队列,由ExecutorService后台执行。
 */
class OkHttpUtils(context: Context) {
    companion object {

        //        private var mOkHttpUtils: OkHttpUtils? = null
//        fun getInstance(context: Context): OkHttpUtils? {
//            if (mOkHttpUtils == null) {
//                synchronized(OkHttpUtils::class.java) {
//                    if (mOkHttpUtils == null) {
//                        mOkHttpUtils = OkHttpUtils(context)
//                    }
//                }
//            }
//            return mOkHttpUtils
//        }
// 自定义委托实现单例,只能修改这个值一次.
        var mOkHttpUtils: OkHttpUtils by DelegatesExt.notNullSingleValue<OkHttpUtils>();
    }
    init {
        //初始化okhttp对象
        mOkHttpUtils =  into(context)
    }

    @Volatile
    private lateinit var mOkHttpClient: OkHttpClient
    private lateinit var mHandler: Handler

    /**
     * 初始化okhttp对象
     * @param context: Context
     * @return OkHttpUtils
     */
    private fun into(context: Context): OkHttpUtils {
        //缓存的文件夹
        val fileCache = File(context.getExternalCacheDir(), "response")
        val cacheSize: Long = 10 * 1024 * 1024//缓存大小为10M
        val cache = Cache(fileCache, cacheSize)
        //进行OkHttpClient的一些设置
        mOkHttpClient = OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)//设置缓存
            .cache(cache)
            .build()
        mHandler = Handler()
        return this
    }





    /**
     * GET同步请求
     * @param url: String
     * @return String?
     */
    open fun get_Sync(url: String): String? {
        val request = Request.Builder()
            .get()
            .url(url)
            .build()
        val call = mOkHttpClient.newCall(request)
        try {
            val response = call.execute()
            if (response.isSuccessful) {
                return response.body?.string()
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }

        return null
    }

    /**
     * GET异步请求
     * @param url: String
     * @param callback: OkHttpCallback
     */
    open fun get_Async(url: String, callback: OkHttpCallback) {
        val request = Request.Builder()
            .url(url)
            .get()
            .build()
        val call = mOkHttpClient.newCall(request)
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                //在UI线程中执行回调
                mHandler.post(Runnable { callback.onError(e) })
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call, response: Response) {
                //在UI线程中执行回调
                mHandler.post(Runnable { callback.onResponse(response) })
            }
        })
    }

    /**
     * POST同步JSON
     * @param url: String
     * @param json: String
     * @return  String?
     */
    open fun post_SyncJSON(url: String, json: String): String? {
        val mediaType = "application/json;charset=utf-8".toMediaTypeOrNull()
        val body = RequestBody.create(mediaType, json)
        val request = Request.Builder()
            .url(url)
            .post(body)
            .build()
        val call = mOkHttpClient.newCall(request)
        try {
            val response = call.execute()
            if (response.isSuccessful) {
                return response.body!!.string()
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }

        return null
    }

    /**
     * POST同步FORM
     * @param url: String
     * @param params: Map<String, String>
     * @return String?
     */
    fun pots_SyncForm(url: String, params: Map<String, String>): String? {

        val body = buildParams(params)
        val request = Request.Builder()
            .url(url)
            .post(body)
            .build()
        val call = mOkHttpClient.newCall(request)
        try {
            val response = call.execute()
            if (response.isSuccessful) {
                return response.body!!.string()
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }

        return null
    }

    /**
     * POST异步JSON
     * @param url: String
     * @param  json: String
     * @param callback: OkHttpCallback
     */
    open fun post_AsyncJSON(url: String, json: String, callback: OkHttpCallback) {

        val mediaType = "application/json;charset=utf-8".toMediaTypeOrNull()
        val body = RequestBody.create(mediaType, json)

        val request = Request.Builder()
            .url(url)
            .post(body)
            .build()
        val call = mOkHttpClient.newCall(request)
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                mHandler.post(Runnable { callback.onError(e) })
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call, response: Response) {
                mHandler.post(Runnable { callback.onResponse(response) })
            }
        })
    }

    /**
     * POST异步FORM
     * @param url: String, params
     * @param params: Map<String, String>
     * @param  callback: OkHttpCallback
     */
    open fun post_AsyncForm(url: String, params: Map<String, String>, callback: OkHttpCallback) {

        val body = buildParams(params)
        val request = Request.Builder()
            .url(url)
            .post(body)
            .build()
        val call = mOkHttpClient.newCall(request)
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                mHandler.post(Runnable { callback.onError(e) })
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call, response: Response) {
                mHandler.post(Runnable { callback.onResponse(response) })
            }
        })
    }

    /**
     * 异步加载文件
     * @param url: String
     * @param callback: OkHttpCallback
     */
    open fun async_LoadFile(url: String, callback: OkHttpCallback) {
        val request = Request.Builder()
            .url(url)
            .get()
            .build()
        val call = mOkHttpClient.newCall(request)
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                mHandler.post(Runnable { callback.onError(e) })

            }

            @Throws(IOException::class)
            override fun onResponse(call: Call, response: Response) {
                mHandler.post(Runnable {
                    //下载文件进度条可以直接在onResponse中实现
                    val `is` = response.body!!.byteStream()
                    //文件的总大小(单位字节)
                    val contentLength = response.body!!.contentLength()

                    var sum: Long = 0//当前下载到的字节量
                    val file = File(Environment.getExternalStorageDirectory(), "girl.png")
                    val fos: FileOutputStream
                    try {
                        fos = FileOutputStream(file)
                        //数组越小进度的密度越高
                        val bytes = ByteArray(128)
                        var len = `is`.read(bytes)
                        while (len != -1) {
                            fos.write(bytes, 0, len)
                            sum += len.toLong()
                            LogUtils.i("progress", "progress=" + sum.toFloat() / contentLength)
                            len = `is`.read(bytes)
                        }
                    } catch (e: FileNotFoundException) {
                        e.printStackTrace()
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }
                })
            }
        })
    }

    /**
     * 异步文件参数混合上传
     * @param  url: String
     * @param params: Map<String, String>?
     * @param  file: File
     * @param  callback: OkHttpCallback 响应回调
     * @param   progressListener: ProgressRequestBody 进度回调
     */
    open fun async_uploadFileAndParams(
        url: String, params: Map<String, String>?, file: File, callback: OkHttpCallback ,
        progressListener:  ProgressRequestBody.ProgressListener) {
        val requestBody = RequestBody.//表示任意二进制流
            create("application/octet-stream".toMediaTypeOrNull(), file)
        //因为是文件参数混合上传,所以要分开构建
        val builder = MultipartBody.Builder()
        builder.setType(MultipartBody.FORM)
        if (params != null) {
            for ((key, value) in params) {
                builder.addFormDataPart(key, value)
            }

        }
        val multipartBody = builder
            //key需要服务器提供,相当于键值对的键
            .addFormDataPart("image", file.getName(), requestBody)
            .build()
        val countingRequestBody = ProgressRequestBody(multipartBody, progressListener)
        val request = Request.Builder()
            .url(url)
            .post(countingRequestBody)
            .build()
        val call = mOkHttpClient.newCall(request)

        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                mHandler.post(Runnable { callback.onError(e) })
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call, response: Response) {
                mHandler.post(Runnable { callback.onResponse(response) })
            }
        })

    }

    /**
     * 参数添加到表单中
     * @param param: Map<String, String>?
     * @return RequestBody
     */
    fun buildParams(param: Map<String, String>?): RequestBody {
        var params: Map<String, String>? = param
        if (params == null) {
            params = HashMap<String, String>()
        }
        val builder = FormBody.Builder()
        for (entry in params.entries) {
            val key = entry.key
            var value: String? = entry.value
            if (value == null) {
                value = ""
            }
            builder.add(key, value)
        }
        return builder.build()
    }

    /**
     * 根据tag取消单个请求
     * 最终的取消时通过拦截器RetryAndFollowUpInterceptor进行的
     * @param call: Call
     */
    open fun cancel(call: Call) {
        //queuedCalls()代表所有准备运行的异步任务
        for (dispatcherCal1 in mOkHttpClient.dispatcher.queuedCalls()) {
            if (call.request().tag()!!.equals(call.request().tag())) {
                call.cancel()
            }
        }
        //runningCalls()代表所有正在运行的任务(包括同步和异步)
        for (dispatcherCal1 in mOkHttpClient.dispatcher.runningCalls()) {
            if (call.request().tag()!!.equals(call.request().tag())) {
                call.cancel()
            }
        }
    }

    /**
     * 取消全部请求
     */
    open fun cancelAll() {
        mOkHttpClient.dispatcher.cancelAll()
    }

    interface OkHttpCallback {
        fun onResponse(response: Response)
        fun onError(e: IOException)
    }


    /*文件加载监听*/
    class ProgressRequestBody(
        body: RequestBody ,
        listener: ProgressListener
    ) : RequestBody() {
        private var mListener: ProgressListener? = listener
        private var mBody: RequestBody? = body
        private var mProgressSink: ProgressSink? = null
        private var mBufferedSink: BufferedSink? = null

        override fun contentType(): MediaType? {
            return mBody!!.contentType();
        }

        override fun writeTo(sink: BufferedSink) {
            //将Sink重新构造
            mProgressSink =  ProgressSink(sink);
            if(mBufferedSink==null) {
                //创建输出流体系  mBufferedSink = Okio.buffer(mProgressSink);
                mBufferedSink = mProgressSink!!.buffer();
            }
            //进行流输出操作
            mBody!!.writeTo(mBufferedSink!!);
            mBufferedSink!!.flush();        }

        override fun contentLength(): Long {
            try {
                return mBody!!.contentLength()
            } catch (e: IOException) {
                return -1
            }

        }

        internal inner class ProgressSink(delegate: Sink) : ForwardingSink(delegate) {
            private var byteWrite: Long = 0//当前写入的字节

            @Throws(IOException::class)
            override fun write(source: Buffer, byteCount: Long) {
                //必须执行父类方法,否则无法上传
                super.write(source, byteCount)
                byteWrite += byteCount
                if (mListener != null) {
                    //更新进度
                    mListener!!.onProgress(byteWrite, contentLength())
                }
            }
        }
        interface ProgressListener {
            fun onProgress(byteWrite: Long, contentLength: Long)
        }
    }

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以回答您的问题。以下是使用Kotlin语言在Android中使用OkHttp获取JSON数据并解析的代码示例: 首先,您需要在您的项目中添加OkHttp库的依赖项。在您的app的build.gradle文件中添加以下代码: ```groovy dependencies { implementation 'com.squareup.okhttp3:okhttp:4.9.0' } ``` 接下来,您可以使用以下代码获取JSON数据: ```kotlin val client = OkHttpClient() val request = Request.Builder() .url("https://example.com/data.json") .build() client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { // 处理失败情况 } override fun onResponse(call: Call, response: Response) { val responseData = response.body()?.string() // 处理响应数据 } }) ``` 在上面的代码中,我们使用OkHttp创建了一个新的HTTP请求并将其排队以异步执行。当响应返回时,我们将调用回调方法以处理响应。 现在,我们需要解析JSON数据。您可以使用Kotlin内置的JSON解析器或Gson等第三方库。以下是使用Kotlin自带的解析器的代码示例: ```kotlin // 假设我们的JSON数据如下: // { // "name": "John Smith", // "age": 30, // "avatarUrl": "https://example.com/avatar.jpg" // } data class User(val name: String, val age: Int, val avatarUrl: String) val user = Json.decodeFromString<User>(responseData) val avatarUrl = user.avatarUrl // 使用Glide库加载图片 Glide.with(context) .load(avatarUrl) .into(imageView) ``` 在上面的代码中,我们首先定义了一个名为User的数据类,该类具有与JSON数据结构相匹配的属性。然后,我们使用Kotlin的JSON解析器从JSON字符串中解析出User对象。最后,我们使用Glide库加载用户的头像图片。 希望这可以帮助您开始使用KotlinOkHttp获取和解析JSON数据!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值