英文:
Api call issue with Retrofit for kotlin using MVP
问题
我正在使用 Kotlin 和 Retrofit 在 MVP 中进行工作。但 API 没有返回响应或完成视图加载。
**presenter 代码**
```kotlin
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 service
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
}
}
如果您需要更详细的解释或其他代码,请告诉我。
英文:
I am working with kotlin using Retrofit in MVP. The API not return the response or finish the view load.
presenter code
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 service
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 is an application call inherits with whole projects
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
}
}
I want to know what mistake in these. Please notify me if any other code needed to more understand.
答案1
得分: 1
根据问题下的评论讨论以及额外发布的代码,我假设并且相当确定问题是在 enqueue
函数中传入了错误类型的回调对象。
目前,enqueue
函数接收的是 Callback<LoginModel>
类型的对象:
CrosspolesApp.instance
?.apiService
?.login(map).enqueue(object: Callback<LoginModel> { ... })
但是根据名为 login
的 ApiService
函数返回的是可选的带有可选的 LoginModel
响应对象的 Call
对象。
这意味着调用 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?>, ...) { ... }
移除空的扩展函数,因为它没有任何用途。
英文:
According to the discussion in the comments under the question and additionally posted code I assume, and mostly sure, that the issue is the wrong type of callback object passed into the enqueue
function.
Currently, the enqueue function receives object of type Callback<LoginModel>
:
CrosspolesApp.instance
?.apiService
?.login(map).enqueue(object: Callback<LoginModel> { ... })
But according to ApiService
function named login
returns optional Call
object with optional LoginModel response object.
It means that the correct way to call enqueue
function would be:
CrosspolesApp.instance
?.apiService
?.login(map)?.enqueue(object: Callback<LoginModel?> { ... })
Since login(map)
returns optional Call
object question mark was placed before calling enqueue
.
Make sure you update Callback
object onResponse
and onFailure
functions implementation (note the question marks):
override fun onResponse(call: Call<LoginModel?>, ...) { ... }
override fun onFailure(call: Call<LoginModel?>, ...) { ... }
Remove the empty extension function as it serves no purpose.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论