美文网首页
Android Kotlin 仿制 JS Axios 简单封装

Android Kotlin 仿制 JS Axios 简单封装

作者: o简单生活o | 来源:发表于2022-03-12 18:38 被阅读0次

一直是一个.NET开发工程师,最近想简单做个APP,遇到网络请求,发现很多人用的Retrofit2,定义了一大堆东西,我这个人喜欢简单的东西,而且我也不是专业做Android的,我就依葫芦画瓢,做了个类似axios结合Promise的功能,代码极少,喜欢的朋友,复制粘贴就能用


需要的依赖

    implementation "com.squareup.okhttp3:okhttp:4.9.3"
    implementation 'com.google.code.gson:gson:2.9.0'

以下是要用到的类和方法

TResult

package com.mqry.utility

class TResult<T> {
    var IsSuccess: Boolean = true
    var Code: Int = 10000
    var Message: String = "操作成功"
    var Description: String = ""
    var Body: T? = null
}

JsonConvert

package com.mqry.utility

import android.util.Log
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.lang.reflect.Type

object JsonConvert {
    fun Serialize(obj: Any): String {
        return Gson().toJson(obj)
    }

    fun <T> Deserialize(json: String): T {
        val type: Type =
            object : TypeToken<T>() {}.type

        var gson = Gson()

        var result = gson.fromJson<T>(
            json.toString(),
            type
        )

        return result
    }

    inline fun <reified T> Any.ToArrayResult(): TResult<ArrayList<T>> {
        return ToArrayResult(this.toString())
    }

    inline fun <reified T> ToArrayResult(json: String): TResult<ArrayList<T>> {

        val type: Type =
            object : TypeToken<TResult<ArrayList<T>>>() {}.type

        var gson = Gson()

        var result = gson.fromJson<TResult<ArrayList<T>>>(
            json.toString(),
            type
        )

        return result
    }

    inline fun <reified T> Any.ToObjectResult(): TResult<T> {
        return ToObjectResult(this.toString())
    }

    inline fun <reified T> ToObjectResult(json: String): TResult<T> {

        val type: Type =
            object : TypeToken<TResult<T>>() {}.type

        var gson = Gson()

        var result = gson.fromJson<TResult<T>>(
            json.toString(),
            type
        )
        return result
    }
}

Axios

package com.mqry.utility

import android.util.Log
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.IOException
import java.util.*


class Axios() {

    companion object {
        lateinit var Instance: Axios

        fun Init() {
            Instance = AxiosBuilder()
                .SetBaseUrl("设置成你要的URL,类似:https://www.baidu.com/")
                .Build()
        }
    }

    enum class AxiosMethod {
        GET, POST
    }

    var BaseUrl: String = ""
    var Headers: MutableMap<String, String> = mutableMapOf()
    var ResponseString: String = ""

    var onComplete: (responseBody: String) -> Promise = { responseBody ->
        Promise.Resolve(responseBody)
    }

    fun Fetch(
        method: AxiosMethod = AxiosMethod.POST,
        url: String,
        data: Any = "{}"
    ): Promise {
        return Promise({ resolve, reject ->

            val builder = Request.Builder()
                .url(this.BaseUrl + url)

            if (method == AxiosMethod.GET) {
                builder.get()
            }

            if (method == AxiosMethod.POST) {
                if (data is String) {
                    builder.post(data.toRequestBody("application/json;charset=utf-8".toMediaType()))
                } else {
                    builder.post(
                        JsonConvert.Serialize(data)
                            .toRequestBody("application/json;charset=utf-8".toMediaType())
                    )
                }
            }

            var request = builder.build()
            val okHttpClient = OkHttpClient()
            val call: Call = okHttpClient.newCall(request)

            try {
                var response = call.execute()
                var responseString = response.body?.string().toString()
                resolve(responseString)
            } catch (e: Exception) {
                reject(e.message)
            }
        })
    }
}

class AxiosBuilder {

    private lateinit var _axios: Axios

    constructor() {
        _axios = Axios()
    }

    fun SetBaseUrl(BaseUrl: String): AxiosBuilder {
        _axios.BaseUrl = BaseUrl
        return this
    }


    fun PutHeader(Key: String, Value: String): AxiosBuilder {
        _axios.Headers.put(Key, Value)
        return this
    }

    /**
     * 我给你一个字符串,你自己处理成你要的Promise对象
     */
    fun OnComplete(executer: (responseBody: String) -> Promise): AxiosBuilder {
        _axios.onComplete = executer
        return this
    }

    fun Build(): Axios {
        return _axios
    }
}

Promise

package com.mqry.utility

import kotlinx.coroutines.*
import java.lang.Exception
import java.lang.Runnable

class Promise() {

    //region 状态枚举
    enum class PROMISE_STATUS {
        PENDING, RESOLVE, REJECT
    }
    //endregion

    //region 属性
    private var _status = PROMISE_STATUS.PENDING
    private var _value: Any? = null

    //未执行的Promise
    private var _nextPromise: Promise? = null
    private var _thisTimeOnResolve: ((Any?) -> Promise)? = null
    private var _thisTimeOnReject: ((Any?) -> Unit)? = null
    //endregion

    //region 构造函数
    constructor(executer: (resolve: (result: Any?) -> Unit, reject: (result: Any?) -> Unit) -> Unit) : this() {
        var that = this
        GlobalScope.launch() {
            try {
                executer(that::_resolve, that::_reject)
            } catch (e: Exception) {
                _reject(e.message.toString())
            }
        }
    }

    constructor(status: PROMISE_STATUS, value: Any? = null) : this() {
        var that = this
        that._status = status
        that._value = value
    }
    //endregion

    //region 处理函数
    /**
     * 成功处理
     */
    private fun _resolve(result: Any? = null) {

        this._value = result
        this._status = PROMISE_STATUS.RESOLVE

        //之前的then没有执行完成,手动执行一次
        if (this._nextPromise != null && this._thisTimeOnResolve != null) {

            var promise = try {
                //结果他没执行完
                _thisTimeOnResolve!!(this._value)
            } catch (e: Exception) {
                Promise.Reject(e.message.toString())
            }

            var maxCount = 0
            //最好的办法,还是等待他处理完
            while (promise._status == PROMISE_STATUS.PENDING) {
                Thread.sleep(100)
                maxCount++
                if (maxCount > 1000) {//超过100秒算失败
                    promise._status = PROMISE_STATUS.REJECT
                }
            }

            if (promise._status == PROMISE_STATUS.RESOLVE) {
                this._nextPromise!!._resolve(promise._value)
            }

            if (promise._status == PROMISE_STATUS.REJECT) {
                this._nextPromise!!._reject(promise._value)
            }
        }
    }

    /**
     * 失败处理
     */
    private fun _reject(result: Any? = null) {
        this._value = result
        this._status = PROMISE_STATUS.REJECT

        if (_thisTimeOnReject == null) {
            this._nextPromise?._reject(this._value)
        } else {
            _thisTimeOnReject!!(this._value)
        }

    }
    //endregion

    //region 核心方法
    fun then(onResolve: (result: Any?) -> Promise): Promise {

        //当下就成功了
        if (_status == PROMISE_STATUS.RESOLVE) {
            try {
                return onResolve(_value)
            } catch (e: Exception) {
                return Promise.Reject(e.message.toString())
            }
        }

        //当下就失败了
        if (_status == PROMISE_STATUS.REJECT) {
            return this
        }

        //未执行完成
        if (_status == PROMISE_STATUS.PENDING) {
            _thisTimeOnResolve = onResolve
            _nextPromise = Promise()
            return _nextPromise as Promise
        }

        throw Exception("未知错误!")
    }

    fun catch(onReject: (result: Any?) -> Unit) {
        if (_status == PROMISE_STATUS.REJECT) {
            onReject(_value)
        }

        //未执行完成
        if (_status == PROMISE_STATUS.PENDING) {
            _thisTimeOnReject = onReject
//            _nextPromise = Promise()
        }
    }
    //endregion

    //region 静态方法
    /**
     * 静态方法
     */
    companion object {

        /**
         * 成功处理
         */
        fun Resolve(value: Any? = null): Promise {
            return Promise(PROMISE_STATUS.RESOLVE, value)
        }

        /**
         * 失败处理
         */
        fun Reject(value: Any? = null): Promise {
            return Promise(PROMISE_STATUS.REJECT, value)
        }

    }
    //endregion
}

相关文章:
Android Kotlin 仿写 JS Promise 链式调用 支持异步


SaliyaService
把你的网络请求写进去

package com.mqry.api

import android.util.Log
import com.mqry.utility.Axios
import com.mqry.utility.Promise

object SaliyaService {
    fun GetOrderFoodCount(Param: Saliya_GetOrderFoodCount_Param): Promise {
        return Axios.Instance.Fetch(url = "/Saliya/GetOrderFoodCount", data = Param)
    }

    fun OrderFood(Param: Saliya_OrderFood_Param): Promise {
        return Axios.Instance.Fetch(url = "/Saliya/OrderFood", data = Param)
    }

    fun ClearOrderFood(Param: Saliya_ClearOrderFood_Param): Promise {
        return Axios.Instance.Fetch(url = "/Saliya/ClearOrderFood", data = Param)
    }

    fun GetOrderFoodList(Param: Saliya_GetOrderFoodList_Param): Promise {
        return Axios.Instance.Fetch(url = "/Saliya/GetOrderFoodList", data = Param)
    }

    fun GetTypeList(Param: Saliya_GetTypeList_Param): Promise {
        return Axios.Instance.Fetch(url = "/Saliya/GetTypeList", data = Param)
    }

    fun GetFoodList(Param: Saliya_GetFoodList_Param): Promise {
        return Axios.Instance.Fetch(url = "/Saliya/GetFoodList", data = Param)
    }

    fun GetStoreList(Param: Saliya_GetStoreList_Param): Promise {
        return Axios.Instance.Fetch(url = "/Saliya/GetStoreList", data = Param)
    }
}

//region Param
data class Saliya_GetOrderFoodCount_Param(
    var PK_StoreGuid: String = "",
    var PK_FoodGuid: String = ""
)

data class Saliya_OrderFood_Param(
    var PK_StoreGuid: String = "",
    var PK_FoodGuid: String = "",
    var Count: Int = 1,
    var Direction: String = "1"
)

data class Saliya_ClearOrderFood_Param(
    var PK_StoreGuid: String = ""
)

data class Saliya_GetOrderFoodList_Param(
    var PK_StoreGuid: String = ""
)

class Saliya_GetTypeList_Param {

}

data class Saliya_GetFoodList_Param(
    var PK_StoreGuid: String = "",
    var TypeID: String = "",
    var FoodName: String = ""
)

class Saliya_GetStoreList_Param {

}
//endregion

//region Result
class Saliya_GetOrderFoodCount_Result {

}

class Saliya_OrderFood_Result {

}

class Saliya_ClearOrderFood_Result {

}

class Saliya_GetOrderFoodList_Result {
    var PK_OrderFoodGuid: String = ""
    var PK_FoodGuid: String = ""
    var PK_StoreGuid: String = ""
    var FoodName: String = ""
    var No: String = ""
    var ImageUrl: String = ""
    var Price: String = ""
    var TotalPrice: Int = 0
    var Count: String = ""
}

class Saliya_GetTypeList_Result {
    var TypeID: String = ""
    var TypeName: String = ""
}

class Saliya_GetFoodList_Result {
    var PK_FoodGuid: String = ""
    var FK_StoreGuid: String = ""
    var ImageUrl: String = ""
    var FoodName: String = ""
    var Description: String = ""
    var Price: String = ""
    var TypeID: String = ""
    var No: String = ""
}

class Saliya_GetStoreList_Result {
    var PK_StoreGuid: String = ""
    var StoreName: String = ""
    var Address: String = ""
    var Telephone: String = ""
    var SaleTime: String = ""
}
//endregion

再找个地方初始化一下Axios

package com.mqry

import android.app.Application
import android.util.Log
import com.mqry.utility.Axios
import com.mqry.utility.AxiosBuilder

class AppLauncher : Application() {
    override fun onCreate() {
        super.onCreate()
        Axios.Init()
    }
}

设置下启动器

启动器配置图
调用示例
package com.mqry

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import com.mqry.api.SaliyaService
import com.mqry.api.Saliya_GetFoodList_Param
import com.mqry.api.Saliya_GetFoodList_Result
import com.mqry.api.Saliya_GetOrderFoodCount_Param
import com.mqry.utility.JsonConvert.ToArrayResult
import com.mqry.utility.JsonConvert.ToObjectResult
import com.mqry.utility.Promise
import com.mqry.utility.TResult

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        SaliyaService.GetOrderFoodCount(
            Saliya_GetOrderFoodCount_Param(
                PK_StoreGuid = "C3358DD8-093C-4377-BDE9-06818D6588AB",
                PK_FoodGuid = "5D5C0772-E44B-4DCF-89D9-204E8F867168"
            )
        ).then { r ->
            Log.i("XX","GetFoodList")
            //这一步的结果集
            var rr: TResult<Int> = r!!.ToObjectResult<Int>()
            //连调
            SaliyaService.GetFoodList(
                Saliya_GetFoodList_Param(
                    PK_StoreGuid = "C3358DD8-093C-4377-BDE9-06818D6588AB",
                    TypeID = "",
                    FoodName = ""
                )
            )
        }.then { r ->
            Log.i("XX","GetOrderFoodCount")
            var rr= r!!.ToArrayResult<Saliya_GetFoodList_Result>()
            Promise.Resolve()
        }.catch { r ->

        }
    }
}

↑↑↑以上就是模仿JS Axios Promise对象的网络请求,懂的朋友可以自行修改和复制粘贴↑↑↑

相关文章

网友评论

      本文标题:Android Kotlin 仿制 JS Axios 简单封装

      本文链接:https://www.haomeiwen.com/subject/hycldrtx.html