不知道Fuel的朋友可以看下下面这几篇文章,这里主要讲项目中的使用流程
GitHub地址
Kotlin网络库Fuel的设计之道
Kotlin实战之Fuel的高阶函数
接入AS:
//fuel框架
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation "com.github.kittinunf.fuel:fuel-rxjava:$fuel_version"
implementation "com.github.kittinunf.fuel:fuel-android:$fuel_version"
implementation "com.github.kittinunf.fuel:fuel-livedata:$fuel_version"
implementation "com.github.kittinunf.fuel:fuel-gson:$fuel_version"
初始化,添加拦截器
import com.github.kittinunf.fuel.core.FuelManager
import com.github.kittinunf.fuel.core.Method
import com.github.kittinunf.fuel.core.Request
import com.sg.dpraise.BuildConfig
import com.sg.dpraise.common.utils.log
/**
* Author:xqt
* Date: 2018/12/21
* Description:初始化fuel网络请求
*/
object FuelTestHelper{
fun initFuel(){
//val requestInterceptors: MutableList<((Request)-> Request)-> ((Request)->Request)> = mutableListOf()
//服务器接口地址
FuelManager.instance.basePath = "http://www.xxxxxx.com"
//超时时间20秒
FuelManager.instance.timeoutInMillisecond = 20000
//FuelManager.instance.baseHeaders = mapOf("token" to "BearerAbCdEf123456")
//添加header拦截器
FuelManager.instance.addRequestInterceptor(tokenInterceptor())
//添加请求日志拦截器
FuelManager.instance.addRequestInterceptor(cUrlLoggingRequestInterceptor())
//foldRight 是 List 的一个扩展函数 从右往左,对列表中的每一个元素执行 operation 操作,
// 每个操作的结果是下一次操作的入参,第一次 operation 的初始值是 initial。
//requestInterceptors.foldRight({r: Request -> r}){f,acc-> f(acc)}
}
/**
* @Author :xqt
* @Description :日志拦截器
* @Return :
* @Params :
*/
private fun cUrlLoggingRequestInterceptor() ={
next: (Request) -> Request ->{
r: Request ->
var logging = StringBuffer()
logging.append("\n-----Method = ${r.method}")
logging.append("\n-----mediaTypes = ${r.mediaTypes}")
logging.append("\n-----headers = ${r.headers}")
logging.append("\n-----url---->${r.url}")
when(r.method){
Method.POST->{
logging.append("\n-----request parameters:")
r.parameters.forEach {
logging.append("\n-----${it.first}=${it.second}")
}
}
}
log(logging)
next(r)
}
}
/**
* @Author :xqt
* @Description :添加header
* @Return :
* @Params :
*/
private fun tokenInterceptor() = {
next: (Request) -> Request ->{
req: Request ->
//"Content-Type:application/x-www-form-urlencoded; charset=UTF-8"
req.header(mapOf("token" to "BearerAbCdEf123456"))//变量替换
next(req)
}
}
}
在application中或者主activity中调用FuelTestHelper.initFuel()方法做初始操作
下面定义所有请求的公共方法:(注:demo里面这里有误,无法解析,请按照下面的代码修改)
-----------------以下需求手动修改--------------------------------
fun Request.request(context: Context,helper: HttpHelper,dialogTip:String? = null){
var dialog = context.createLoadingDialog(dialogTip)
this.rx_responseString()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe{result->
dialog?.stopLoadingDialog()
val (_, rt) = result
val err = rt.component2()
if (err == null) {//请求成功
log(rt.component1())
var resp = Gson().fromJson(rt.component1(), Resp::class.java)
when(resp?.code){
0-> {
var data = Gson().fromJson(resp.data, helper.rawType)
helper.onReqFinish(data, 0)
}
else-> {
toast(resp.msg)
helper.onReqFinish(null, -1)
}
}
} else {//请求失败
helper.onReqFinish(null,-1)
log(err.toString())
var msg = Error.REQUEST_ERROR
when(err.exception){
is JsonSyntaxException -> msg = Error.PARSER_ERROR
is ConnectException -> msg = Error.NET_ERROR
is SocketTimeoutException -> msg = Error.NET_TIMEOUT_ERROR
is HttpException -> msg = Error.SERVER_ERROR
is UnknownHostException -> msg = Error.NET_ERROR
}
toast(msg)
}
}
}
/**
* @Author :xqt
* @Description :创建对话框
* @Return :
* @Params :
*/
fun Context.createLoadingDialog(msg:String? = null):LoadingDialog? {
var loadingDialog = LoadingDialog(this, R.style.loadingdialog)//创建Dialog并设置样式主题
loadingDialog?.setCancelable(false)
loadingDialog?.show()
if (msg != null){
loadingDialog?.setLoadMsg(msg)
}
return loadingDialog
}
/**
* @Author :xqt
* @Description :关闭
* @Return :
* @Params :
*/
fun LoadingDialog?.stopLoadingDialog() {
if (this!=null && this?.isShowing){
this?.dismiss()
}
}
HttpHelper方便回调可自行定义:
/**
* 请求回调
*/
abstract class HttpHelper {
abstract fun onReqFinish(data: T?, code: Int)
/**
* @Author :xqt
* @Description :延迟初始化
*/
val rawType: Type by lazy {
getSuperclassTypeParameter(javaClass)
}
companion object {
fun getSuperclassTypeParameter(cls:Class<*>): Type {
val superclass = cls.genericSuperclass
if (superclass is Class<*>) {
throw RuntimeException("Missing type parameter.")
}
val parameterized = superclass as ParameterizedType
return `$Gson$Types`.canonicalize(parameterized.actualTypeArguments[0])
}
}
}
Resp数据解析类:
/**
* 基础返回数据结构
*/
data class Resp (
var code:Int = -10000,
var data: T? = null,
var msg: String? = null
)
-----------------以上需求手动修改--------------------------------
实际调用:
import android.view.View
import com.github.kittinunf.fuel.httpGet
import com.sg.dpraise.R
import com.sg.dpraise.bean.frame.UserModel
import com.sg.dpraise.common.utils.isMyEmpty
import com.sg.dpraise.common.utils.setStatusColor
import com.sg.dpraise.common.utils.toast
import com.sg.dpraise.frame.base.BaseFragmentActivity
import com.sg.dpraise.http.ApiConstant
import com.sg.dpraise.http.HttpHelper
import com.sg.dpraise.http.request
import kotlinx.android.synthetic.main.activity_login_layout.*
import org.jetbrains.anko.startActivity
/**
* Author:xqt
* Date: 2018/12/27
* Description:
*/
class LoginActivity : BaseFragmentActivity() {
override fun getLayoutResId() = R.layout.activity_login_layout
/**
* @Description :初始化操作
*/
override fun initView() {
}
/**
* @Description :initView调用完成后调用 做数据初始操作
*/
override fun initData() {
}
fun onClick(v: View){
when(v.id){
R.id.R_tvLogin -> login()
R.id.R_tvForgotPwd -> forgotPwd()
R.id.R_tvRegister -> register()
}
}
/**
* @Description :注册
*/
private fun register() {
startActivity()
}
/**
* @Description :忘记密码
*/
private fun forgotPwd() {
startActivity()
}
/**
* @Description :登录
*/
private fun login() {
var phone = R_editPhone.text.toString()
var pwd = R_editPwd.text.toString()
when {
phone.isMyEmpty() -> {
toast("手机号不能为空")
return
}
pwd.isMyEmpty() -> {
toast("密码不能为空")
return
}
pwd.length < 6 -> {
toast("密码不能小于6位")
return
}
else -> {
//登录
ApiConstant.LOGIN_API.httpGet(listOf("phone" to phone,"password" to pwd))
.request(this,object: HttpHelper {
override fun onReqFinish(data: UserModel?, code: Int) {
//处理结果
if (code == 0){
//登录成功
}
}
})
// ApiConstant.LOGIN_API.httpPost(listOf("phone" to phone,"password" to pwd))
// .request(this,object: HttpHelper> {
// override fun onReqFinish(data: List?, code: Int) {
// //处理结果
// if (code == 0){
// //登录成功
// }
// }
// })
}
}
}
}
这里使用接口地址直接调用的方式(ApiConstant.LOGIN_API)
object ApiConstant {
const val LOGIN_API = "/api/shop/login"
const val FORGOT_PWD_API = "/api/shop/forgetPwd"
}
demo下载