AndroidSDK开发6我用kotlin协程写了一个简单sdk

  • Post author:
  • Post category:其他



目录


AndroidSDK开发6我用kotlin协程写了一个简单sdk


1.kotlin的依赖和导包如下:(//如果不使用协程可以去掉协程的导包减少sdk包大小)


2.Application代码如下:


3.常量工具类(Constants):


4.日志工具类(LogUtils):


5.网络状态工具类(NetWorkUtils):


6.初始化及管理工具类(WanAndroidManager):


7.网络请求工具类:


8.网络请求接口监听:


9.网络请求结果解析工具类:


10.网络请求接口回调方法:


11.网络请求线程工具类:


12.网络请求回调:


13.网络请求封装的具体方法(包含请求参数和结果回调):


14.具体测试代码如下:(由于之前讲过怎么在新项目中引入aar,这里就不重复了,不懂的小伙伴可以看前几篇)


15.运行效果截图和日志:


15.1 具体实现效果截图如下:


15.2 运行日志如下:


16.项目源码地址如下(分支选择dev_kotlin):

AndroidSDK开发6我用kotlin写了一个简单sdk

由于前面几篇文章讲解了sdk初始化、sdk设计原则、将moule或者项目打成aar、不用第三方库开发一个sdk等,目前市面上很少有使用sdk开发采用kotlin语言,本文讲解使用如何使用kolin开发一个简单sdk,当然这里有2个版本,由于最开始没有使用协程导致使用和代码还是很多,经过之前的经验和sdk使用原则以及对新语言的使用情况,于是产生了使用加入协程的概念,具体使用如下:

1.kotlin的依赖和导包如下:

(如果不使用协程可以去掉协程的导包减少sdk包大小)

//apply plugin: 'com.android.application'
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

dependencies {   implementation fileTree(dir: “libs”, include: [“*.jar”])   implementation ‘androidx.appcompat:appcompat:1.1.0’   implementation ‘androidx.constraintlayout:constraintlayout:1.1.3’   implementation “org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version”   implementation “org.jetbrains.kotlin:kotlin-reflect:$kotlin_version”   implementation “org.jetbrains.kotlinx:kotlinx-coroutines-core:${kotlinx_coroutines_version}” }

2.Application代码如下:

/**
 * @auth: njb
 * @date: 2022/4/27 15:56
 * @desc: 描述
 */
class App : Application() {
​
    override fun onCreate() {
        super.onCreate()
        context = applicationContext
    }
​
    companion object{
        var context: Context by Delegates.notNull()
            private set
    }
}

3.常量工具类(Constants):

/**
 * @auth: njb
 * @date: 2022/4/25 11:43
 * @desc: 常量工具类
 */
object Constants {
    const val BASE_URL = "https://www.wanandroid.com"
    const val DEFAULT_TIMEOUT = 20000 //10秒
    const val TAG = "WanHttp"
    //搜索
    const val QUERY_ARTICLE = "/article/query/0/json"
    //获取首页banner列表
    const val BANNER_LIST = "/banner/json"
    //搜索热词
    const val HOT_KEY = "/hotkey/json"
}

4.日志工具类(LogUtils):

/**
 * @auth: njb
 * @date: 2022/4/26 14:26
 * @desc: 日志工具类
 */
object LogUtils {
    const val showLog:Boolean = true
​
    fun i(tag: String, msg: String) {
        if (showLog) Log.i(tag, msg)
    }
​
    fun d(tag: String, msg: String) {
        if (showLog) Log.d(tag, msg)
    }
​
    fun w(tag: String, msg: String) {
        if (showLog) Log.w(tag, msg)
    }
​
    fun e(tag: String, msg: String) {
        if (showLog) Log.e(tag, msg)
    }
}

5.网络状态工具类(NetWorkUtils):

/**
 * @auth: njb
 * @date: 2022/4/27 11:45
 * @desc: 网络状态工具类
 */
class NetWorkUtils {
    companion object{
        @get:RequiresPermission(Manifest.permission.ACCESS_NETWORK_STATE)
        val isConnected: Boolean
            get() {
                val info = activeNetworkInfo
                return info.isConnected
            }
​
        @get:RequiresPermission(Manifest.permission.ACCESS_NETWORK_STATE)
        private val activeNetworkInfo: NetworkInfo
            get() {
                val cm = App.context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
                return cm.activeNetworkInfo!!
            }
    }
}

6.初始化及管理工具类(WanAndroidManager):

/**
 * @auth: njb
 * @date: 2022/4/23 22:39
 * @desc: 描述
 */
class WanAndroidManager() {
    var mContext:Context by Delegates.notNull()
​
    fun init(app: Application){
        mContext = app.applicationContext
    }
}

7.网络请求工具类:

class WanHttpUtils {
    companion object {
        lateinit var connection: HttpURLConnection
        fun doRequestPost(params: Map<String, String>): WanAndroidHttpResult<String> {
            val result by lazy { WanAndroidHttpResult<String>() }
            try {
                runBlocking {
                    withContext(Dispatchers.Default) {
                        val url by lazy { URL(params["url"]) }
                        LogUtils.d(Constants.TAG, "$url --url--")
                        setConnection(url, params)
                        LogUtils.d(Constants.TAG, "$params --params--")
                        val requestParamJsonObject by lazy { params["body"] }
                        if (requestParamJsonObject != null && "" != requestParamJsonObject?.trim { it <= ' ' }) {
                            val bytes by lazy { requestParamJsonObject?.toByteArray() }
                            connection.setRequestProperty("Content-Length", bytes?.size.toString())
                            val outputStream by lazy { connection.outputStream }
                            outputStream.run {
                                write(bytes)
                                flush()
                                close()
                            }
                        }
                        setResult(responseCode = connection.responseCode, result)
                    }
                }
            } catch (e: Exception) {
                showErrorMsg(result, e)
            } finally {
                connection.disconnect()
            }
            return result
        }
​
        fun doRequestGet(params: Map<String, String>): WanAndroidHttpResult<String>? {
            val result by lazy { WanAndroidHttpResult<String>() }
            runBlocking {
                withContext(Dispatchers.Default) {
                    try {
                        val url by lazy { URL(params["url"]) }
                        setConnection(url, params)
                        setResult(responseCode = connection.responseCode, result)
                    } catch (e: Exception) {
                        showErrorMsg(result, e)
                    }
                }
            }
            return result
        }
​
        private fun setResult(responseCode: Int, result: WanAndroidHttpResult<String>) {
            result.run {
                responseCode.run {
                    if (this == 200) {
                        isBizSucceed(true)
                        setData(getResponseDataString(connection.inputStream))
                    } else {
                        isBizSucceed(false)
                        setData("")
                        result.errorMsg =
                            "errorCode:" + responseCode + connection.responseMessage
                    }
                }
            }
        }
​
        private fun setConnection(
            url: URL,
            params: Map<String, String>,
        ) {
            connection = (url.openConnection() as HttpURLConnection).apply {
                readTimeout = DEFAULT_TIMEOUT
                connectTimeout = DEFAULT_TIMEOUT
                doOutput = true
                doInput = true
                requestMethod = params["Method"]
                setRequestProperty("Connection", "Keep-Alive")
                setRequestProperty("Charset", "UTF-8")
                setRequestProperty("Content-Type", "application/json; charset=UTF-8")
                setRequestProperty("accept", "application/json")
            }
        }
​
        private fun showErrorMsg(result: WanAndroidHttpResult<String>, e: Exception) {
            val msg: Any
            msg = when {
                !isConnected -> {
                    "网络连接失败,请检查网络"
                }
                e is SocketTimeoutException -> {
                    "网络请求超时,请稍后重试"
                }
                e is MalformedJsonException -> {
                    "数据解析失败"
                }
                else -> {
                    "请求失败,请稍后重试:" + e.message
                }
            }
            result.errorMsg = msg
        }
​
        private fun getResponseDataString(inputStream: InputStream): String {
            val inputStreamReader by lazy { InputStreamReader(inputStream) }
            val bufferedReader by lazy { BufferedReader(inputStreamReader) }
            val stringBuilder by lazy { StringBuilder() }
            var temp: String?
            try {
                while (bufferedReader.readLine().also { temp = it } != null) {
                    stringBuilder.append(temp)
                }
            } catch (e: IOException) {
                e.printStackTrace()
            } finally {
                try {
                    bufferedReader.close()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
                try {
                    inputStreamReader.close()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
                try {
                    inputStream.close()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
            return stringBuilder.toString()
        }
    }
}

8.网络请求接口监听:

/**
 * @auth: njb
 * @date: 2022/6/10 15:59
 * @desc: 描述
 */
interface OnResponseListener {
   suspend fun onResponse(wanAndroidHttpResult: WanAndroidHttpResult<*>?)
}

9.网络请求结果解析工具类:

/**
 * @auth: njb
 * @date: 2022/4/22 15:53
 * @desc: 描述
 */
class WanAndroidHttpResult<T> {
    /**
     * 记录请求回来的错误状态描述
     */
    private var errorCode:Int ?=0
​
    /**
     * 记录请求回来的错误状态描述
     */
    var errorMsg = ""
​
    /**
     * 记录返回的数据
     */
    var data: T? = null
        private set
​
    /**
     * 业务请求是否成功
     */
    fun isBizSucceed(defaultValue: Boolean): Boolean {
        return if (null == errorCode) defaultValue else errorCode == 0
    }
​
    fun setData(data: T) {
        this.data = data
    }
}

10.网络请求接口回调方法:

/**
 * @auth: njb
 * @date: 2022/4/22 15:33
 * @desc: 描述
 */
interface WanHttpRequestCallBack {
    fun onResponse(response: String?): Boolean?
​
    fun onFailed(message: String?): Boolean?
}

11.网络请求线程工具类:

/**
 * @auth: njb
 * @date: 2022/6/6 10:06
 * @desc: 描述
 */
open class WanRequestThread(
    private val params: Map<String, String>,
    private val listener: OnResponseListener
) {
    private val lock by lazy { ByteArray(0) }
    private var isCancel = false
​
    suspend fun run() {
        val result: WanAndroidHttpResult<String>? =
            if (params["Method"] == "POST") WanHttpUtils.doRequestPost(params) else WanHttpUtils.doRequestGet(params)
            if (!isCancel) {
                listener.onResponse(result)
            }
    }
​
    suspend fun cancel() {
        synchronized(lock) { isCancel = true }
    }
}

12.网络请求回调:

/**
 * @auth: njb
 * @date: 2022/6/6 10:27
 * @desc: 描述
 */
class WanRequestListener {
    companion object{
        suspend fun getQueryArticle(responseListener: OnResponseListener, keyWord:String): WanRequestThread {
            val params by lazy { HashMap<String, String>() }
            val url by lazy { Constants.BASE_URL + Constants.QUERY_ARTICLE + "?k="+keyWord }
            params["url"] = url
            params["Method"] = "POST"
            val requestThread by lazy { WanRequestThread(params, responseListener) }
            requestThread.run()
            return requestThread
        }
    }
​
    suspend fun getHomeBanner(responseListener: OnResponseListener):WanRequestThread{
        val params by lazy { HashMap<String, String>() }
        val url by lazy { Constants.BASE_URL + Constants.BANNER_LIST }
        params["url"] = url
        params["Method"] = "GET"
        val requestThread by lazy { WanRequestThread(params, responseListener) }
        requestThread.run()
        return requestThread
    }
}

13.网络请求封装的具体方法(包含请求参数和结果回调):

/**
 * @auth: njb
 * @date: 2022/5/2 22:37
 * @desc: 描述
 */
object WanHttpRequest {
    suspend fun queryArticle(callBack: WanHttpRequestCallBack,keyWord:String){
        WanRequestListener.getQueryArticle(object : OnResponseListener {
            override suspend fun onResponse(wanAndroidHttpResult: WanAndroidHttpResult<*>?) {
                if (wanAndroidHttpResult == null && wanAndroidHttpResult?.data == null) {
                    return
                }
                try {
                    val content by lazy { wanAndroidHttpResult.data.toString() }
                    wanAndroidHttpResult.run {
                        callBack.run {
                            if (isBizSucceed(true)) {
                                onResponse(content)
                            } else {
                                val message by lazy { wanAndroidHttpResult.errorMsg }
                                onFailed(message)
                            }
                        }
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        },keyWord)
    }
}

14.具体测试代码如下:

(由于之前讲过怎么在新项目中引入aar,这里就不重复了,不懂的小伙伴可以看前几篇)

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
    }
​
    private fun initView() {
        getQueryData()
    }
​
    private fun getQueryData() {
        GlobalScope.launch(Dispatchers.Main) {
            WanHttpRequest.queryArticle(object : WanHttpRequestCallBack {
                override fun onResponse(response: String?): Boolean? {
                    try {
                        val jsonObject by lazy { JSONObject(response) }
                        val jsonObject2 = jsonObject.getJSONObject("data")
                        val jsonArray by lazy { jsonObject2.getJSONArray("datas") }
                        val list: MutableList<ArticleListDataBean> = ArrayList()
                        if (jsonArray.length() > 0) {
                            for (i in 0 until jsonArray.length()) {
                                val datasBean = ArticleListDataBean()
                                val bannerObject: JSONObject = jsonArray.getJSONObject(i)
                                datasBean.run {
                                    bannerObject.run {
                                        id = bannerObject.getInt("id")
                                        link = bannerObject.getString("link")
                                        desc = bannerObject.getString("desc")
                                        apkLink = bannerObject.getString("apkLink")
                                        title = bannerObject.getString("title")
                                        chapterName = bannerObject.getString("chapterName")
                                    }
                                    list.add(this)
                                }
                            }
                            CoroutineScope(Dispatchers.IO).launch {
                                list.forEach { it ->
                                    Log.d("---MainActivity---", it.chapterName + " 数据获取成功 ")
                                    tvTest.text = it.chapterName
                                }
                            }
                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                    return null
                }
                override fun onFailed(message: String?): Boolean? {
                    return null
                }
            }, "Android")
        }
    }
}

15.运行效果截图和日志:

15.1 具体实现效果截图如下:

/**

这里使用的是鸿洋的WanAndroidApi,只是写了一个简单的接口测试,没有写具体的逻辑 **

/


15.2 运行日志如下:


16.项目源码地址如下(分支选择dev_kotlin):


wanandroidsdkHttp: 利用鸿神wanandroidapi封装的简单sdk,没有使用任何第三方



版权声明:本文为u012556114原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。