java - 使用 MVP 对 Kotlin 进行改造的 Api 调用问题
问题描述
我正在使用 MVP 中的 Retrofit 与 kotlin 合作。API 不返回响应或完成视图加载。
演示者代码
import android.content.Context
import android.util.Log
import com.crosspoles.CrosspolesApp
import com.crosspoles.R
import com.crosspoles.Views.LoginView
import com.ruhe.model.LoginModel
import okhttp3.RequestBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.util.*
class LoginPresenter : BasePresenter<LoginView?>() {
fun LoginUser(activity:Context, map:HashMap<String, RequestBody>, progress:Boolean) {
view!!.enableLoadingBar(activity, progress, activity.getResources().getString(R.string.loading))
CrosspolesApp.instance
?.apiService
?.login(map).enqueue(object:Callback<LoginModel> {
override fun onResponse(call:Call<LoginModel>, response:Response<LoginModel>) {
view!!.enableLoadingBar(activity, false, "")
view!!.onLoginComplete(response.body(), response.code())
Log.e("@@Start","dsadas")
}
override fun onFailure(call:Call<LoginModel>, t:Throwable) {
Log.e("@@Start2","dsadas")
view!!.enableLoadingBar(activity, false, "")
try {
t.printStackTrace()
}
catch (e:Exception) {
e.printStackTrace()
}
view!!.onError(null)
}
})
}
}
private fun <T> Call<T>?.enqueue(callback: Callback<LoginModel>) {
}
API服务
package com.crosspoles.service
import com.crosspoles.model.LoginModel
import okhttp3.RequestBody
import retrofit2.Call
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.PartMap
import java.util.*
interface ApiService {
@Multipart
@POST("login")
fun login(@PartMap map: HashMap<String, RequestBody>): Call<LoginModel?>?
}
CrosspolesApp是与整个项目一起继承的应用程序调用
package com.crosspoles
import android.content.Context
import android.os.StrictMode
import androidx.multidex.MultiDex
import androidx.multidex.MultiDexApplication
import com.crosspoles.service.ApiService
import com.crosspoles.service.CustomInterceptor
import com.facebook.stetho.Stetho
import com.google.gson.GsonBuilder
import com.crosspoles.extra.Constants
import io.github.inflationx.calligraphy3.CalligraphyConfig
import io.github.inflationx.calligraphy3.CalligraphyInterceptor
import io.github.inflationx.viewpump.ViewPump
import okhttp3.Cache
import okhttp3.ConnectionPool
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import java.io.File
import java.util.*
import java.util.concurrent.TimeUnit
class CrosspolesApp : MultiDexApplication() {
var isAidl = false
var apiService: ApiService? = null
private set
override fun onCreate() {
super.onCreate()
instance = this
MultiDex.install(applicationContext)
createApiService()
val builder = StrictMode.VmPolicy.Builder()
StrictMode.setVmPolicy(builder.build())
ViewPump.init(ViewPump.builder()
.addInterceptor(CalligraphyInterceptor(
CalligraphyConfig.Builder()
.setDefaultFontPath("fonts/open_sans_regular.ttf")
.setFontAttrId(R.attr.fontPath)
.build()))
.build())
Stetho.initializeWithDefaults(this)
}
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
}
fun createApiService(): ApiService? {
val gson = GsonBuilder().create()
val httpCacheDirectory = File(cacheDir, "cache_file")
val cache = Cache(httpCacheDirectory, 20 * 1024 * 1024)
val okHttpClient = OkHttpClient.Builder()
.connectTimeout(2, TimeUnit.MINUTES)
.writeTimeout(2, TimeUnit.MINUTES)
.readTimeout(2, TimeUnit.MINUTES)
.connectionPool(ConnectionPool(0, 5 * 60 * 1000, TimeUnit.SECONDS))
.addInterceptor(CustomInterceptor(instance, Locale.getDefault().language, appVersion))
.cache(cache)
.build()
val retrofit = Retrofit.Builder().client(okHttpClient)
.baseUrl(Constants.BASE_crosspoles_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
apiService = retrofit.create(ApiService::class.java)
return apiService
}
private val appVersion: String
private get() = try {
packageManager.getPackageInfo(packageName, 0).versionName
} catch (e: Exception) {
e.printStackTrace()
"1.1"
}
companion object {
var instance: CrosspolesApp? = null
private set
}
}
我想知道这些有什么错误。如果需要更多了解其他代码,请通知我。
解决方案
根据问题下评论中的讨论以及另外发布的代码,我假设并且大部分可以肯定的是,问题是传递给enqueue
函数的回调对象类型错误。
目前,入队函数接收类型为Callback<LoginModel>
:
CrosspolesApp.instance
?.apiService
?.login(map).enqueue(object: Callback<LoginModel> { ... })
但是根据ApiService
命名的函数login
返回可选Call
对象和可选的 LoginModel响应对象。
这意味着调用enqueue
函数的正确方法是:
CrosspolesApp.instance
?.apiService
?.login(map)?.enqueue(object: Callback<LoginModel?> { ... })
由于login(map)
返回可选Call
对象问号放置在调用之前enqueue
。
确保更新Callback
对象onResponse
和onFailure
函数实现(注意问号):
override fun onResponse(call: Call<LoginModel?>, ...) { ... }
override fun onFailure(call: Call<LoginModel?>, ...) { ... }
删除空扩展功能,因为它没有任何作用。
推荐阅读
- c - 如何安全地将任意文本作为参数传递给 shell 脚本中的程序?
- shell - Mac OSx 终端:函数定义上的“不是有效标识符”
- ios12 - WatchOS5 - 如何立即刷新我的并发症?
- node.js - NodeJS + 请求 REST API
- firebase - 如何从测试中访问 Firebase Flutter 插件?
- node.js - chromeLauncher/Lighthouse:使用 Jest 模拟返回承诺的链式依赖项
- linux - 为什么有些 Bash 命令既是内置的又是外置的?
- java - Java 无法确定要调用的方法
- react-native - 反应原生。如何在垂直对齐中心的行中放置两个具有不同字体大小的文本
- javascript - 骨干嵌入式收集事件