开发Android也有些时间了,一直想把一些基础的组件和功能封装起来,做成一个简单的android开发框架,以备以后的使用和开发,今天就把之前的一些代码整理出来,当然了,也有很多代码是参考了网上的,这里我就不一一鸣谢了。
网络请求是所有App中必须要实现的,从最开始的HttpUrlConnection,到HttpClient,再到Volley,以至于Retrofit,当然了,还有很多http库,可以说选择众多,也各有所长;这里主要是介绍Google的开源框架Volley,以前对它的一些封装。
开发语言:Kotlin
开源框架:Volley EventBus Anko Okhttp Fastjson
Volley封装
VolleyExtensions.kt
package com.vslimit.kotlindemo.util.net.volley
import android.content.res.Resources
import com.android.volley.*
import com.vslimit.kotlindemo.R
fun VolleyError.toString(res: Resources): String {
when {
isApiError() -> return getApiErrorMessage(res)
isNetworkError() -> return res.getString(R.string.no_data_connection)
this is TimeoutError -> return res.getString(R.string.generic_server_down)
else -> return res.getString(R.string.generic_error)
}
}
private fun VolleyError.isNetworkError() = this is NetworkError || this is NoConnectionError
private fun VolleyError.isApiError() = this is ServerError || this is AuthFailureError
/** @return A user readable message that interprets the cause of the Api failure. */
private fun VolleyError.getApiErrorMessage(res: Resources): String {
if (networkResponse != null) {
when (networkResponse.statusCode) {
404 -> return res.getString(R.string.no_results_found)
422, 401, 411, 417 -> {
return res.getString(R.string.generic_error)
}
else -> return res.getString(R.string.generic_server_down)
}
}
return res.getString(R.string.generic_error)
}
inline fun <reified T : Any> RequestQueue.add(listener: Listener<T>?,
url: String,
noinline configure: ((Request<*>) -> Any)? = null,
method: Int = Request.Method.GET) {
val volleyListener = Response.Listener<T> { r -> listener?.onCompleted(null, r) }
val errorListener = Response.ErrorListener { e -> listener?.onCompleted(e, null) }
val request = FastJsonRequest(method, url, T::class.java, volleyListener, errorListener)
configure?.invoke(request)
this.add(request)
}
inline fun <reified T : Any> RequestQueue.post(listener: Listener<T>?,
url: String,
noinline configure: ((Request<*>) -> Any)? = null,
param: MutableMap<String, String> = hashMapOf()) {
val volleyListener = Response.Listener<T> { r -> listener?.onCompleted(null, r) }
val errorListener = Response.ErrorListener { e -> listener?.onCompleted(e, null) }
val request = NormalPostRequest(url, T::class.java, volleyListener, errorListener, param)
configure?.invoke(request)
this.add(request)
}
NormalPostRequest
package com.vslimit.kotlindemo.util.net.volley
import android.util.Log
import com.alibaba.fastjson.JSON
import com.android.volley.*
import com.android.volley.Response.Listener
import com.android.volley.toolbox.HttpHeaderParser
import org.json.JSONException
import java.io.UnsupportedEncodingException
/**
* Created by vslimit on 16/5/26.
*/
class NormalPostRequest<T>(url: String, private val clazz: Class<T>, private val mListener: Listener<T>, errorListener: Response.ErrorListener, private val mMap: Map<String, String>) : Request<T>(Method.POST, url, errorListener) {
//mMap是已经按照前面的方式,设置了参数的实例
@Throws(AuthFailureError::class)
override fun getParams(): Map<String, String> {
return mMap
}
//此处因为response返回值需要json数据,和JsonObjectRequest类一样即可
override fun parseNetworkResponse(response: NetworkResponse): Response<T> {
try {
val jsonString = String(response.data)
Log.d("return json:::", jsonString)
return Response.success(JSON.parseObject(jsonString, clazz), HttpHeaderParser.parseCacheHeaders(response))
} catch (e: UnsupportedEncodingException) {
return Response.error<T>(ParseError(e))
} catch (je: JSONException) {
return Response.error<T>(ParseError(je))
}
}
override fun deliverResponse(response: T) {
mListener.onResponse(response)
}
}
FastJsonRequest
package com.vslimit.kotlindemo.util.net.volley
import android.util.Log
import com.alibaba.fastjson.JSON
import com.android.volley.*
import com.android.volley.Response.*
import com.android.volley.toolbox.HttpHeaderParser
import com.android.volley.Response.Listener
/**
* Created by vslimit on 16/1/19.
*/
open class FastJsonRequest<T> : Request<T> {
private val clazz: Class<T>
private val headerz: MutableMap<String, String> by lazy { hashMapOf("Accept" to "application/json") }
private val listener: Listener<T>
private var param: MutableMap<String, String> = hashMapOf()
constructor(url: String, clazz: Class<T>, listener: Listener<T>, errorListener: ErrorListener) :
super(Method.GET, url, errorListener) {
this.clazz = clazz
this.listener = listener
}
constructor(method: Int, url: String, clazz: Class<T>, listener: Listener<T>, errorListener: ErrorListener) :
super(method, url, errorListener) {
this.clazz = clazz
this.listener = listener
}
constructor(method: Int, url: String, clazz: Class<T>, listener: Listener<T>, errorListener: ErrorListener, param: MutableMap<String, String>) :
super(method, url, errorListener) {
this.clazz = clazz
this.listener = listener
this.param = param
}
@Throws(AuthFailureError::class)
override fun getHeaders(): Map<String, String> = headerz
@Throws(AuthFailureError::class)
override fun getParams(): Map<String, String> = param
override fun deliverResponse(response: T) = listener.onResponse(response)
override fun parseNetworkResponse(response: NetworkResponse?): Response<T>? {
try {
val json = String(response!!.data)
Log.d("return json:::", json)
return success(JSON.parseObject(json, clazz), HttpHeaderParser.parseCacheHeaders(response))
} catch(e: Exception) {
return error<T>(ParseError(e))
}
}
}
在App中使用OKHttp处理Volley底层请求
App
package com.vslimit.kotlindemo
import android.app.Application
import android.content.Context
import android.support.multidex.MultiDex
import com.android.volley.RequestQueue
import com.android.volley.toolbox.HurlStack
import com.android.volley.toolbox.Volley
import com.squareup.okhttp.OkHttpClient
import com.squareup.okhttp.OkUrlFactory
import java.io.IOException
import java.net.HttpURLConnection
import java.net.URL
import kotlin.properties.Delegates
class App : Application() {
companion object {
var instance: App by Delegates.notNull()
var queue: RequestQueue? = null
}
override fun onCreate() {
super.onCreate()
instance = this
queue = initQueue()
}
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
MultiDex.install(this)
}
fun initQueue(): RequestQueue {
val factory = OkUrlFactory(OkHttpClient())
val hurlStack = object : HurlStack() {
@Throws(IOException::class) override fun createConnection(url: URL): HttpURLConnection {
return factory.open(url)
}
}
return Volley.newRequestQueue(this, hurlStack)
}
}
项目中使用
fun init() {
if (NetworkUtil.isNetwork(act)) {
val listener = Listener<IPResult> { e, r ->
e?.let { Bus.post(BaseEvent<IPResult>(error = e)) }
r?.let { Bus.post(BaseEvent(response = r)) }
}
val url = "http://ip.taobao.com/service/getIpInfo.php?ip=63.223.108.42"
Log.d("Url:::", "")
App.queue!!.add(listener, url)
//post 调用
//App.queue!!.post(listener, url, hashMapOf("aaa" to "aaa", "bbb" to "bbb"))
toast("正在加载中...")
} else {
alert("网络错误", "网络未连接,请检查网络")
}
}
fun onEventMainThread(event: BaseEvent<IPResult>) {
val error = event.error
result = event.response
info(result)
toast("加载完成!!!")
if (error != null) {
toast(error.toString(resources))
} else {
if (result!!.code == Result.SUCCESS) {
async() {
uiThread {
resultTv.text = result!!.data!!.country
}
}
} else {
toast(result!!.code)
}
}
}
至此,完成了对Volley封装,项目中直接使用即可。