【问题标题】:Android Kotlin Retrofit + Rxjava rest call not returning requested dataAndroid Kotlin Retrofit + Rxjava 休息调用不返回请求的数据
【发布时间】:2019-09-21 02:53:38
【问题描述】:

我有一个用 Kotlin 编写的 Android 应用程序,它从 API 获取数据,现在它只是一个本地托管的 JSON 文件。当我尝试获取数据时,我收到错误,即我的列表 people 未初始化,因此 people == null 并且没有收到数据。我不确定我做错了什么以及如何解决这个问题。

型号

data class Person (
  @Json(name = "personId")
  val personId: Int,

  @Json(name = "personName")
  val name: String,

  @Json(name = "personAge")
  val age: Int,

  @Json(name = "isFemale")
  val isFemale: Boolean,
)

JSON 响应

{
  "persons": [{
      "personId": 1,
      "personName": "Bert",
      "personAge": 19,
      "isFemale": "false",
    }
  ]
}

ApiClient

class ApiClient {
    companion object {

        private const val BASE_URL = "http://10.0.2.2:3000/"

        fun getClient(): Retrofit {
            val moshi = Moshi.Builder()
                .add(customDateAdapter)
                .build()

            return Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(MoshiConverterFactory.create(moshi))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build()
        }
    }
}

改造 http 方法

interface ApiInterface {

    @GET("persons")
    fun getPersons(): Observable<List<Person>>
}

最后是通话

class PersonActivity: AppCompatActivity(){
  private lateinit var jsonAPI: ApiInterface
  private lateinit var persons: List<Person>

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_person)

    val retrofit = ApiClient.getClient()
    jsonAPI = retrofit.create(ApiInterface::class.java)
    jsonAPI.getPersons()
            .subscribeOn(Schedulers.io())
            .unsubscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({ persons = it })
  }
}

预期:JSON 文件中的数据进入人员列表而不是 NULL。

【问题讨论】:

  • 您的响应不是人员列表,而是对象“人员”,该对象具有一个..许多人员对象。
  • @GiorgosNeokleous 那么我怎样才能得到一个列表呢?我尝试添加 PersonResponse { lateinit var data: List } 但它没有用
  • 我将在下面以答案格式发布它

标签: android kotlin retrofit rx-java2 moshi


【解决方案1】:

您的 moshi 适配器直接期望 person 对象,但它们嵌套在 "persons" Json 数组中。

你应该添加另一个模型如下

data class Persons (
    @Json(name="persons")
    val persons : List<Person>
)

同时更改接口以返回新对象。

interface ApiInterface {
    @GET("persons")
    fun getPersons(): Observable<Persons>
}

还需要将订阅更改为

.subscribe({ persons = it.persons })

【讨论】:

  • 虽然你说的很有道理,但它仍然不起作用。但我在我的 Rest 服务器上也看不到请求,我在 localhost:3000 上托管,并被告知使用 10.0.2.2:3000 代替,以便模拟器可以访问它。
  • 这是另一个问题,对吧?如果您无法访问您的 API,则问题不在于解析。检查stackoverflow.com/a/33256827/3330058以启用登录Retrofit以检查错误
  • 我想是的,我不确定,但我看不到任何请求,所以我认为他们永远不会通过?不过,我可以通过我的网络浏览器完美地访问 API。
  • 好吧,我确实看到了现在的请求,我忘了将 usesCleartextTraffic 添加到 AndriodManifest 文件中。但我仍然有错误,persons 没有初始化
  • 是的,这正是我所做的,仍然收到人员未初始化的错误,调试时我可以看到人员为空
【解决方案2】:

我认为可能是两个问题之一。

如果您使用 moshi 反射,您将在 gradle 中拥有类似这些依赖项:

//Moshi Core
implementation "com.squareup.moshi:moshi:1.8.0"

//Moshi Reflection
implementation "com.squareup.moshi:moshi-kotlin:1.8.0"

在这种情况下,您将需要使用 KotlinJsonAdapterFactory:

  val moshi = Moshi.Builder()
        .add(customDateAdapter)
        .add(KotlinJsonAdapterFactory())
        .build()

如果您使用的是 codegen,您将需要这个:

apply plugin: 'kotlin-kapt'
...
//Moshi Core Artifact
implementation "com.squareup.moshi:moshi:1.8.0"

//Moshi Codegen
kapt "com.squareup.moshi:moshi-kotlin-codegen:1.8.0"

此外,您要反序列化的每个类都应使用注释 @JsonClass(generateAdapter = true)(所以是 Person 和 Persons 类)

【讨论】:

    猜你喜欢
    • 2019-09-25
    • 1970-01-01
    • 1970-01-01
    • 2020-11-25
    • 2018-05-07
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 2015-07-26
    相关资源
    最近更新 更多