一、首先添加项目的Kotlin支持,这个不概述了,网上很多我主要就是讲述我怎么写的Kotlin网络请求
二、使用的开源项目
implementation 'com.squareup.okhttp3:okhttp:3.14.2'
implementation 'com.google.code.gson:gson:2.8.5'
其次还得加上
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
三、封装网络请求
1、先看看使用方式
2、实现
1)先看目录结构
2)创建OkHttphelper的单例Kotlin文件
在init方式中初始化需要网络请求的资源
init {
okHttpClient = OkHttpClient().newBuilder()
.readTimeout(60, TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(60, TimeUnit.SECONDS)//设置写的超时时间
.connectTimeout(60, TimeUnit.SECONDS)//设置连接超时时间
//https支持
.hostnameVerifier { hostname, session -> true }
.sslSocketFactory(initSSLSocketFactory(), initTrustManager())
.build()
mHandler = Handler(Looper.getMainLooper())
mGson = Gson()
}
支持ssl的方法
private fun initSSLSocketFactory(): SSLSocketFactory {
var sslContext: SSLContext? = null
try {
sslContext = SSLContext.getInstance("SSL")
val xTrustArray = arrayOf(initTrustManager())
sslContext.init(
null,
xTrustArray, SecureRandom()
)
} catch (e: Exception) {
e.printStackTrace()
}
return sslContext!!.socketFactory
}
private fun initTrustManager(): X509TrustManager {
return object : X509TrustManager {
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
}
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
}
}
}
3)创建枚举类定义请求的类型(get,post,上传,下载)
enum class HttpMethodType {
GET, POST, UPLOAD_FILE, DOWNLOAD_FILE
}
4)创建BaseCallback方法,所有的请求处理类都会继承他
open class BaseCallback<T> {
var mType: Type? = null
init {
mType = getSuperclassTypeParameter(javaClass)
}
companion object {
internal fun getSuperclassTypeParameter(subClass: Class<*>): Type {
val superclass = subClass.genericSuperclass
if (superclass is Class<*>) {
throw RuntimeException("Missing type parameter.")
}
val parameterizedType = superclass as ParameterizedType
return `$Gson$Types`.canonicalize(parameterizedType.actualTypeArguments[0])
}
}
open fun onRequestBefore(request: Request) {}
open fun onFailure(request: Request, e: IOException) {}
open fun onSuccess(response: Response, t: Any) {}
open fun onError(response: Response, code: Int, e: Exception) {}
open fun onResponse(response: Response) {}
open fun onProgress(response: Response, total: Long, current: Long) {}
}
5)创建Requet
private fun buildRequest(url: String, params: MutableMap<String, String>?, methodType: HttpMethodType): Request {
val builder = Request.Builder()
builder.url(url)
when (methodType) {
HttpMethodType.GET -> {
mHttpMethodType = HttpMethodType.GET
builder.get()
}
HttpMethodType.POST -> {
mHttpMethodType = HttpMethodType.POST
builder.post(buildFormData(params))
}
HttpMethodType.UPLOAD_FILE -> {
mHttpMethodType = HttpMethodType.UPLOAD_FILE
builder.post(buildFileData(params))
}
HttpMethodType.DOWNLOAD_FILE -> {
mHttpMethodType = HttpMethodType.DOWNLOAD_FILE
try {
this.mParams?.clear()
this.mParams = params
} catch (e: Exception) {
e.printStackTrace()
}
}
}
return builder.build()
}
6)创建doRequest方法因为下载需要进度条,所有区分请求
private fun doRequest(request: Request, callback: BaseCallback<*>) {
callback.onRequestBefore(request)
okHttpClient.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
callback.onFailure(call.request(), e)
}
override fun onResponse(call: Call, response: Response) {
if (mHttpMethodType == HttpMethodType.DOWNLOAD_FILE) {
if (response.isSuccessful) {
val length = response.body()!!.contentLength()
if (length == 0L) {
return
}
var inputS: InputStream? = null
var fos: FileOutputStream? = null
val buff = ByteArray(2048)
var len: Int = 0
var flag: Boolean = true
val localPath = mParams?.get("localPath")
val downEntity = DownLoadEntity(
"" + mParams?.get("localPath"),
"" + mParams?.get("serverPath")
)
try {
inputS = response.body()!!.byteStream()
var current: Long = 0
if (TextUtils.isEmpty(localPath)) {
callback.onResponse(response)
throw RuntimeException("localPath is miss")
}
val file = File(localPath)
if (file.exists()) {
file.delete()
}
fos = FileOutputStream(file)
while (flag) {
len = inputS.read(buff)
flag = len != -1
if (flag) {
callBackProgress(callback, response, length, current)
current += len.toLong()
fos.write(buff, 0, len)
}
}
fos.flush()
} catch (e: Exception) {
callback.onResponse(response)
e.printStackTrace()
} finally {
try {
inputS?.close()
fos?.close()
} catch (e: Exception) {
callback.onResponse(response)
e.printStackTrace()
}
callback.onResponse(response)
callBackSuccess(callback, response, downEntity)
}
} else {
callBackError(callback, response, response.code(), null)
}
} else {
callback.onResponse(response)
if (response.isSuccessful) {
if (callback.mType == String::class.java) {
val resultStr = response.body()!!.string()
Log.i("wxf", "server_data->" + resultStr)
callBackSuccess(callback, response, resultStr)
} else if ("" + callback.mType == "byte[]") {
callBackSuccess(callback, response, response.body()!!.bytes())
} else {
try {
val resultStr = response.body()!!.string()
Log.i("wxf", "server_data->" + resultStr)
val mObject = Gson().fromJson<Any>(resultStr, callback.mType)
callBackSuccess(callback, response, mObject)
} catch (e: Exception) {
e.printStackTrace()
callBackError(callback, response, response.code(), e)
}
}
}
}
}
})
}
7)创建以上四个请求方法
fun get(url: String, baseCallback: BaseCallback<*>) {
doRequest(buildRequest(url, null, HttpMethodType.GET), baseCallback)
}
fun post(url: String, params: MutableMap<String, String>?, baseCallback: BaseCallback<*>) {
doRequest(buildRequest(url, params, HttpMethodType.POST), baseCallback)
}
/**
* this map must have localFilePath parma
*/
fun upLoadFile(url: String, params: MutableMap<String, String>, callback: BaseCallback<*>) {
doRequest(buildRequest(url, params, HttpMethodType.UPLOAD_FILE), callback)
}
/**
* this must have localPath parma
*/
fun downLoadFile(url: String, params: MutableMap<String, String>?, callback: BaseCallback<*>) {
if (params != null) {
if (TextUtils.isEmpty(params.get("localPath"))) {
throw RuntimeException("map localPath is miss")
} else {
mParams?.put("localPath", "" + params?.get("localPath"))
}
if (!TextUtils.isEmpty(url)) {
mParams?.put("serverPath", url)
}
}
doRequest(buildRequest(url, params, HttpMethodType.DOWNLOAD_FILE), callback)
}
四、所有类的完整代码
1)DownLoadEntity
data class DownLoadEntity(
val localPath: String,
val serverPath: String
)
2)FileCallBack
abstract class FileCallBack<T> : BaseCallback<DownLoadEntity> {
internal var dialog: ProgressDialog? = null
private var msg: String? = null
constructor(context: Context) {
if (dialog == null) {
dialog = ProgressDialog(context)
dialog!!.setCanceledOnTouchOutside(false)
}
dialog!!.setMessage("加载中......")
}
constructor(context: Context, message: String) {
if (dialog == null) {
dialog = ProgressDialog(context)
dialog!!.setCanceledOnTouchOutside(false)
}
this.msg = message
dialog!!.setMessage(message)
}
override fun onRequestBefore(request: Request) {
showDialog()
}
override fun onFailure(request: Request, e: IOException) {
dissmissDialog()
}
override fun onResponse(response: Response) {
dissmissDialog()
}
override fun onProgress(response: Response, total: Long, current: Long) {
try {
if (TextUtils.isEmpty(msg)) {
msg = "加载中"
}
if (dialog != null && dialog!!.isShowing)
dialog!!.setMessage(msg + (current * 1f / total * 100).toInt() + "%")
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun dissmissDialog() {
if (dialog != null && dialog!!.isShowing) {
dialog!!.dismiss()
dialog = null
}
}
private fun showDialog() {
if (dialog != null && !dialog!!.isShowing) {
dialog!!.show()
}
}
}
3)OkHttpHelper
object OkHttpHelper {
private val okHttpClient: OkHttpClient
private val mHandler: Handler
private val mGson: Gson
private var mHttpMethodType: HttpMethodType? = null
private var mParams: MutableMap<String, String>? = null
init {
okHttpClient = OkHttpClient().newBuilder()
.readTimeout(60, TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(60, TimeUnit.SECONDS)//设置写的超时时间
.connectTimeout(60, TimeUnit.SECONDS)//设置连接超时时间
//https支持
.hostnameVerifier { hostname, session -> true }
.sslSocketFactory(initSSLSocketFactory(), initTrustManager())
.build()
mHandler = Handler(Looper.getMainLooper())
mGson = Gson()
}
private fun initSSLSocketFactory(): SSLSocketFactory {
var sslContext: SSLContext? = null
try {
sslContext = SSLContext.getInstance("SSL")
val xTrustArray = arrayOf(initTrustManager())
sslContext.init(
null,
xTrustArray, SecureRandom()
)
} catch (e: Exception) {
e.printStackTrace()
}
return sslContext!!.socketFactory
}
private fun initTrustManager(): X509TrustManager {
return object : X509TrustManager {
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
}
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
}
}
}
private fun buildFormData(params: Map<String, String>?): RequestBody {
val body = FormBody.Builder()
Log.i("wxf", "params::" + params.toString())
if (params != null) {
params.forEach {
try {
if (!TextUtils.isEmpty(it.key)) {
body.add(it.key, it.value)
}
} catch (e: Exception) {
}
}
}
return body.build()
}
private fun buildFileData(params: Map<String, String>?): RequestBody {
val builder = MultipartBody.Builder()
builder.setType(MultipartBody.FORM)
if (params != null) {
params.forEach {
try {
if (!TextUtils.isEmpty(it.key)) {
if (it.key == "file") {
val file = File(it.value)
builder.addFormDataPart(
it.key, file.name,
RequestBody.create(null, file)
)
} else {
builder.addFormDataPart(it.key, "" + it.value)
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
return builder.build()
}
private fun buildRequest(url: String, params: MutableMap<String, String>?, methodType: HttpMethodType): Request {
val builder = Request.Builder()
builder.url(url)
when (methodType) {
HttpMethodType.GET -> {
mHttpMethodType = HttpMethodType.GET
builder.get()
}
HttpMethodType.POST -> {
mHttpMethodType = HttpMethodType.POST
builder.post(buildFormData(params))
}
HttpMethodType.UPLOAD_FILE -> {
mHttpMethodType = HttpMethodType.UPLOAD_FILE
builder.post(buildFileData(params))
}
HttpMethodType.DOWNLOAD_FILE -> {
mHttpMethodType = HttpMethodType.DOWNLOAD_FILE
try {
this.mParams?.clear()
this.mParams = params
} catch (e: Exception) {
e.printStackTrace()
}
}
}
return builder.build()
}
private fun callBackError(callback: BaseCallback<*>, response: Response, code: Int, e: Exception?) {
if (mHttpMethodType != HttpMethodType.DOWNLOAD_FILE) {
mHandler.post { callback.onError(response, code, e!!) }
} else {
callback.onError(response, code, e!!)
}
}
private fun callBackSuccess(callback: BaseCallback<*>, response: Response, mObject: Any) {
if (mHttpMethodType != HttpMethodType.DOWNLOAD_FILE) {
mHandler.post {
callback.onSuccess(response, mObject)
}
} else {
callback.onSuccess(response, mObject)
}
}
private fun callBackProgress(callback: BaseCallback<*>, response: Response, total: Long, current: Long) {
mHandler.post { callback.onProgress(response, total, current) }
}
private fun doRequest(request: Request, callback: BaseCallback<*>) {
callback.onRequestBefore(request)
okHttpClient.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
callback.onFailure(call.request(), e)
}
override fun onResponse(call: Call, response: Response) {
if (mHttpMethodType == HttpMethodType.DOWNLOAD_FILE) {
if (response.isSuccessful) {
val length = response.body()!!.contentLength()
if (length == 0L) {
return
}
var inputS: InputStream? = null
var fos: FileOutputStream? = null
val buff = ByteArray(2048)
var len: Int = 0
var flag: Boolean = true
val localPath = mParams?.get("localPath")
val downEntity = DownLoadEntity(
"" + mParams?.get("localPath"),
"" + mParams?.get("serverPath")
)
try {
inputS = response.body()!!.byteStream()
var current: Long = 0
if (TextUtils.isEmpty(localPath)) {
callback.onResponse(response)
throw RuntimeException("localPath is miss")
}
val file = File(localPath)
if (file.exists()) {
file.delete()
}
fos = FileOutputStream(file)
while (flag) {
len = inputS.read(buff)
flag = len != -1
if (flag) {
callBackProgress(callback, response, length, current)
current += len.toLong()
fos.write(buff, 0, len)
}
}
fos.flush()
} catch (e: Exception) {
callback.onResponse(response)
e.printStackTrace()
} finally {
try {
inputS?.close()
fos?.close()
} catch (e: Exception) {
callback.onResponse(response)
e.printStackTrace()
}
callback.onResponse(response)
callBackSuccess(callback, response, downEntity)
}
} else {
callBackError(callback, response, response.code(), null)
}
} else {
callback.onResponse(response)
if (response.isSuccessful) {
if (callback.mType == String::class.java) {
val resultStr = response.body()!!.string()
Log.i("wxf", "server_data->" + resultStr)
callBackSuccess(callback, response, resultStr)
} else if ("" + callback.mType == "byte[]") {
callBackSuccess(callback, response, response.body()!!.bytes())
} else {
try {
val resultStr = response.body()!!.string()
Log.i("wxf", "server_data->" + resultStr)
val mObject = Gson().fromJson<Any>(resultStr, callback.mType)
callBackSuccess(callback, response, mObject)
} catch (e: Exception) {
e.printStackTrace()
callBackError(callback, response, response.code(), e)
}
}
}
}
}
})
}
fun get(url: String, baseCallback: BaseCallback<*>) {
doRequest(buildRequest(url, null, HttpMethodType.GET), baseCallback)
}
fun post(url: String, params: MutableMap<String, String>?, baseCallback: BaseCallback<*>) {
doRequest(buildRequest(url, params, HttpMethodType.POST), baseCallback)
}
/**
* this map must have localFilePath parma
*/
fun upLoadFile(url: String, params: MutableMap<String, String>, callback: BaseCallback<*>) {
doRequest(buildRequest(url, params, HttpMethodType.UPLOAD_FILE), callback)
}
/**
* this must have localPath parma
*/
fun downLoadFile(url: String, params: MutableMap<String, String>?, callback: BaseCallback<*>) {
if (params != null) {
if (TextUtils.isEmpty(params.get("localPath"))) {
throw RuntimeException("map localPath is miss")
} else {
mParams?.put("localPath", "" + params?.get("localPath"))
}
if (!TextUtils.isEmpty(url)) {
mParams?.put("serverPath", url)
}
}
doRequest(buildRequest(url, params, HttpMethodType.DOWNLOAD_FILE), callback)
}
}
enum class HttpMethodType {
GET, POST, UPLOAD_FILE, DOWNLOAD_FILE
}
4)SpotsCallBack
abstract class SpotsCallBack<T> : BaseCallback<T> {
private var dialog: ProgressDialog? = null
private var isShow: Boolean = true
constructor(mContext: Context) {
try {
if (dialog == null)
dialog = ProgressDialog(mContext)
setMessage("加载中......")
} catch (e: Exception) {
// e.printStackTrace()
}
}
constructor(mContext: Context, isShow: Boolean) {
try {
if (dialog == null)
dialog = ProgressDialog(mContext)
this.isShow = isShow
setMessage("加载中......")
} catch (e: Exception) {
// e.printStackTrace()
}
}
constructor(context: Context, message: String) {
try {
if (dialog == null)
dialog = ProgressDialog(context)
} catch (e: Exception) {
// e.printStackTrace()
}
setMessage(message)
}
override fun onRequestBefore(request: Request) {
if (isShow) showDialog()
}
override fun onFailure(request: Request, e: IOException) {
dismissDialog()
}
override fun onProgress(response: Response, total: Long, current: Long) {
}
abstract override fun onSuccess(response: Response, t: Any)
abstract override fun onError(response: Response, code: Int, e: Exception)
override fun onResponse(response: Response) {
dismissDialog()
}
private fun showDialog() {
try {
if (dialog != null && !dialog!!.isShowing)
dialog?.show()
} catch (e: Exception) {
// e.printStackTrace()
}
}
private fun dismissDialog() {
try {
if (dialog != null && dialog!!.isShowing)
dialog?.dismiss()
} catch (e: Exception) {
// e.printStackTrace()
}
}
private fun setMessage(message: String) {
try {
if (dialog != null && !TextUtils.isEmpty(message))
dialog!!.setMessage(message)
} catch (e: Exception) {
// e.printStackTrace()
}
}
}
五、注意
1、在kotlin中也可以写basejson类,只不过需要写为open类
open class BaseJson {
var code: Int?=null
var msg: String?=null
var message: String?=null
var errorCode: String?=null
var score: Int?=null
}
2、使用的时候可以直接继承就好
data class UpdateVersionclazz(
val ret: UpdateRet
) : BaseJson() {
data class UpdateRet(
val version: String,
val version_no: String,
val url: String,
val forced: String
)
}