Android-1 Kotlin Volley

开发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  RequestQueue.add(listener: Listener?,
                                              url: String,
                                              noinline configure: ((Request<*>) -> Any)? = null,
                                              method: Int = Request.Method.GET) {

    val volleyListener = Response.Listener { 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  RequestQueue.post(listener: Listener?,
                                               url: String,
                                               noinline configure: ((Request<*>) -> Any)? = null,
                                               param: MutableMap = hashMapOf()) {

    val volleyListener = Response.Listener { 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(url: String, private val clazz: Class, private val mListener: Listener, errorListener: Response.ErrorListener, private val mMap: Map) : Request(Method.POST, url, errorListener) {

    //mMap是已经按照前面的方式,设置了参数的实例
    @Throws(AuthFailureError::class)
    override fun getParams(): Map {
        return mMap
    }

    //此处因为response返回值需要json数据,和JsonObjectRequest类一样即可
    override fun parseNetworkResponse(response: NetworkResponse): Response {
        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(ParseError(e))
        } catch (je: JSONException) {
            return Response.error(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 : Request {

    private val clazz: Class
    private val headerz: MutableMap by lazy { hashMapOf("Accept" to "application/json") }
    private val listener: Listener

    private var param: MutableMap = hashMapOf()

    constructor(url: String, clazz: Class, listener: Listener, errorListener: ErrorListener) :
    super(Method.GET, url, errorListener) {
        this.clazz = clazz
        this.listener = listener
    }

    constructor(method: Int, url: String, clazz: Class, listener: Listener, errorListener: ErrorListener) :
    super(method, url, errorListener) {
        this.clazz = clazz
        this.listener = listener
    }

    constructor(method: Int, url: String, clazz: Class, listener: Listener, errorListener: ErrorListener, param: MutableMap) :
    super(method, url, errorListener) {
        this.clazz = clazz
        this.listener = listener
        this.param = param
    }

    @Throws(AuthFailureError::class)
    override fun getHeaders(): Map = headerz

    @Throws(AuthFailureError::class)
    override fun getParams(): Map = param


    override fun deliverResponse(response: T) = listener.onResponse(response)

    override fun parseNetworkResponse(response: NetworkResponse?): Response? {
        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(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 { e, r ->
                e?.let { Bus.post(BaseEvent(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) {
        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封装,项目中直接使用即可。

更多代码详见:https://github.com/vslimit/kotlindemo

你可能感兴趣的:(Android-1 Kotlin Volley)