Api 调用失败无法为类 Retrofit/Moshi 创建转换器

Rus*_*G.H 10 post android kotlin retrofit moshi

我正在实施改造莫希向服务器发出请求(我是使用改造的新手)。我遵循在互联网上找到的一些关于如何实现它的指南,但是在启动应用程序时,我收到以下错误:

Error Api call failed Unable to create converter for class com.example.kvn.data.model.JConfig
     for method ApiClient.getApiConfig
Run Code Online (Sandbox Code Playgroud)

这是我使用的代码:

应用程序模块.kt

@Module
@InstallIn(ApplicationComponent::class)
object AppModule {

    @Singleton
    @Provides
    fun providerDB(@ApplicationContext ctx: Context) =
        Room.databaseBuilder(ctx, AppDB::class.java, DB_NAME).build()

    @Singleton
    @Provides
    fun providerDao(db: AppDB) = db.getDao()

    @Singleton
    @Provides
    fun provideHttpClient(): OkHttpClient {
        return OkHttpClient
            .Builder()
            .readTimeout(15, TimeUnit.SECONDS)
            .connectTimeout(15, TimeUnit.SECONDS)
            .build()
    }

    @Singleton
    @Provides
    fun provideConverterFactory() = MoshiConverterFactory.create()

    @Singleton
    @Provides
    fun provideRetrofit(
        okHttpClient: OkHttpClient,
        moshiConverterFactory: MoshiConverterFactory
    ): Retrofit {
        return Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(moshiConverterFactory)
            .build()
    }

    @Singleton
    @Provides
    fun providerApi(retrofit: Retrofit) = retrofit.create(ApiClient::class.java)
}
Run Code Online (Sandbox Code Playgroud)

远程.kt

/*@JsonClass(generateAdapter = true)
data class JConfig(
    @Json(name = "data") val data:List<Config>
)

data class Config(
    @Json(name = "codigo") var codigo: Int,
    @Json(name = "tipo") var tipo: String,
    @Json(name = "empresa") var empresa: Int,
    @Json(name = "sucursal") var sucursal: Int,
    @Json(name = "esquema") var esquema: Int,
    @Json(name = "horainicio") var hini: String,
    @Json(name = "horafinal") var hfin: String,
    @Json(name = "fecha") var fecha: String,
    @Json(name = "seguimiento") var seguimiento: Int
)*/

@JsonClass(generateAdapter = true)
data class JConfig(
    @Json(name = "data") val data:List<Config>
)

data class Config(
    var codigo: Int,
    var tipo: String,
    var empresa: Int,
    var sucursal: Int,
    var esquema: Int,
    var horainicio: String,
    var horafinal: String,
    var fecha: String,
    var seguimiento: Int
)
Run Code Online (Sandbox Code Playgroud)

ApiClient.kt

interface ApiClient {

    @POST(API_CONFIGURACION)
    suspend fun getApiConfig(@Body imei: String): Response<JConfig>
}
Run Code Online (Sandbox Code Playgroud)

Web数据源.kt

class WebDataSource @Inject constructor(private val web:ApiClient) {

    suspend fun getWebConfiguracion(imei:String): Response<JConfig> {
        return web.getApiConfig(imei)
    }
}
Run Code Online (Sandbox Code Playgroud)

AppViewModel.kt

class AppViewModel @ViewModelInject constructor(private val repository: Repository) : ViewModel() {

    private val _response: MutableLiveData<NetworkResult<JConfig>> = MutableLiveData()
    val response: LiveData<NetworkResult<JConfig>> = _response

    fun fetchConfigResponse(imei:String) = viewModelScope.launch {
        repository.getWebConfiguracion(imei).collect { values ->
            _response.value = values
        }
    }

    fun saveOrUpdateConf(conf:Config) {
        viewModelScope.launch {
            if (isConfigEmpty()) {
                repository.saveConfiguracion(conf)
            }else {
                repository.updateConfiguracion(conf)
            }
        }
    }

    suspend fun setupConfig(T:()->Unit) {
        if (isConfigEmpty()) {
            T()
        }else {
            val cf = repository.getConfiguracion().value!!
            if (yesterday(cf[0].fecha)) {
                T()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

FBase.kt

@AndroidEntryPoint
class FBase : Fragment() {

    private val viewmodel by activityViewModels<AppViewModel>()
    private var _bind:FragmentFBaseBinding? = null
    private val bind get() = _bind!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _bind = FragmentFBaseBinding.inflate(inflater, container, false)
        return bind.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setupObserver("888888882222331")
    }

    private fun setupObserver(imei:String) {
        fetchResponse(imei)
        viewmodel.response.observe(viewLifecycleOwner) { response ->
            when(response) {
                is NetworkResult.Loading -> { /*Notification*/ }
                is NetworkResult.Success -> {
                    val rs = response.data?.data?.get(0)!!
                    viewmodel.saveOrUpdateConf(rs)
                }
                is NetworkResult.Error -> { Log.d("TAG","Error ${response.message}") }
            }
        }
    }

    private fun fetchResponse(imei: String) {
        viewmodel.fetchConfigResponse(imei)
        //add notification
    }
}
Run Code Online (Sandbox Code Playgroud)

依赖项和插件

plugins {
   id 'com.android.application'
   id 'kotlin-android'
   id 'kotlin-android-extensions'
   id 'kotlin-kapt'
   id 'dagger.hilt.android.plugin'
}

//  HILT
implementation 'com.google.dagger:hilt-android:2.28.1-alpha'
kapt 'com.google.dagger:hilt-android-compiler:2.28.1-alpha'
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'
//  TOOLS
implementation 'com.squareup.moshi:moshi-kotlin:1.13.0'
implementation 'com.squareup.moshi:moshi:1.13.0'
kapt 'com.squareup.moshi:moshi-kotlin-codegen:1.13.0'
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
Run Code Online (Sandbox Code Playgroud)

在retrofit之前,我和moshi一起使用volley进行请求没有任何问题,但是retrofit之后我不知道如何解决。

对不起我的英语不好。

谢谢

Ato*_*rce 13

就我而言,这是因为我没有将moshi对象传递给 MoshiConverterFactory.create() 例如

private val retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create())
.baseUrl(BASE_URL)
.build()
Run Code Online (Sandbox Code Playgroud)

编译正常,但会抛出 OP 在运行时看到的相同错误。

通过将 moshi 传递到 MoshiConverterFactory 来修复

private val retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(BASE_URL)
.build()
Run Code Online (Sandbox Code Playgroud)

moshi 对象定义为

private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
Run Code Online (Sandbox Code Playgroud)

  • 我花了很长时间才找到这个。谢谢 (2认同)

Rus*_*G.H 12

我找到了错误的根源,当使用 moshi 进行改造时,所有数据类必须具有以下注释@JsonClass(generateAdapter = true)

我们必须更改代码:

@JsonClass(generateAdapter = true)
data class JConfig(
    @Json(name = "data") val data:List<Config>
)

data class Config(
    var codigo: Int,
    var tipo: String,
    var empresa: Int,
    var sucursal: Int,
    var esquema: Int,
    var horainicio: String,
    var horafinal: String,
    var fecha: String,
    var seguimiento: Int
)
Run Code Online (Sandbox Code Playgroud)

为了这:

@JsonClass(generateAdapter = true)
data class JConfig(
    @Json(name = "data") val data:List<Config>
)

@JsonClass(generateAdapter = true)
data class Config(
    var codigo: Int,
    var tipo: String,
    var empresa: Int,
    var sucursal: Int,
    var esquema: Int,
    var horainicio: String,
    var horafinal: String,
    var fecha: String,
    var seguimiento: Int
)
Run Code Online (Sandbox Code Playgroud)