android - Android Kotlin RxJava Retrofit - 空 DisposableObserver LiveData
问题描述
我正在 Kotlin 中实现一个 Android 应用程序,它使用 API 作为数据的主要来源。我使用 Kotlin、RXjava、Retrofit 和 Dagger 来使其工作。
但由于某种原因,我在 onNext 函数中的 person 对象是空的。尽管我在 Logcat 中看到了 http 方法调用数据,并且它具有正确的 person 对象。
我从 JSON 请求一个人对象:
{
"persons": [{
"personId": 1,
"personName": "Bert",
"personAge": 19,
"isFemale": "false",
"birthDate": "2000-06-28T00:00:00"
}
]
}
接口接口:
@GET("persons")
fun getPerson(@Query("personId") personId: Int): Observable<Person>
人员存储库:
class PersonRepository @Inject constructor(val apiInterface: ApiInterface) {
fun getPerson(personId: Int): Observable<Person>{
return apiInterface.getPerson(personId)
}
}
人视图模型:
class PersonViewModel @Inject constructor(private val personRepositoy: PersonRepository) : ViewModel() {
var personResult: MutableLiveData<Person> = MutableLiveData()
var personError: MutableLiveData<String> = MutableLiveData()
lateinit var disposableObserver: DisposableObserver<Person>
fun personResult(): LiveData<Person> {
return personResult
}
fun personError(): LiveData<String> {
return personError
}
fun loadPerson(personId: Int) {
disposableObserver: object : DisposableObserver<Person>() {
override fun onComplete() {}
override fun onNext(person: Person){ //this is empty for some reason
personResult.postValue(person)
}
override fun onError(e: Throwable) {
personError.postValue(e.message)
}
}
personRepository.getPerson(personId)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(disposableObserver)
}
fun disposeElements() {
if(null !- disposableObserver && !disposableObserver.isDisposed) {
disposableObserver.dispose()
}
}
}
进行调用的 PersonActivity:
@Inject
lateinit var personViewModelFactory: PersonViewModelFactory
lateinit var personViewModel: PersonViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_person)
AndroidInjection.inject(this)
personViewModel = ViewModelProviders.of(this, personViewModelFactory).get(PersonViewModel::class.java)
personViewModel.loadPerson(1)
personViewModel.personResult().observe(this, Observer<Person> {
//some code that uses it
}
}
getPerson 调用返回正确的人,我可以在日志中看到,但它不会像我想要的那样在 personResult 中发布值。我不知道为什么。
编辑:按要求添加了 Person 类。请注意,@Json 是 GSON 中的 @SerializedName 的 Moshi 等价物。
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(name = "birthDate")
val birthDate: GregorianCalendar
)
解决方案
为了避免 JSON 响应和要使用的实际对象不匹配,定义一个类似这样的中间类:
data class PersonResponse(
@Json(name = "persons")
val persons: List<Person>
)
示例 api 类:
@GET("persons")
fun getPerson(@Query("personId") personId: Int): Observable<PersonResponse>
@GET("persons")
fun getAllPersons(): Observable<PersonResponse>
示例存储库类:
fun getPerson(personId: Int): Observable<Person>{
// Convert PersonResponse -> Person
return apiInterface.getPerson(personId)
.doOnNext { value -> Log.d(SOME_LOG_TAG, "onNext: value=$value") }
.doOnError { error -> Log.d(SOME_LOG_TAG, "onNext: value=${e.getMessage()}") }
.flatMap { response ->
// Check if the list contains exactly one Person and throw error if it doesn't
if (response.persons.size == 1)
Observable.just(response.persons[0])
else
Observable.error(Throwable("Something's wrong"))
}
}
fun getAllPerson(): Observable<List<Person>> {
// Convert PersonResponse -> List<Person>
return apiInterface.getAllPersons()
.map { response -> response.persons }
}
如您所见,存储库代码可能看起来很混乱。我建议在您的 api 类和存储库类之间建立一个中间层来完成所有转换。
推荐阅读
- powershell - PowerShell Graph-API 退出代码
- ios - 获取 UserDefaults 不会返回任何内容
- powershell - Powershell 正在复制文件夹的内容,但忽略了复制文件夹
- unit-testing - 如何在 Azure DevOps 管道中对基于硬件的许可代码进行单元测试?
- x86 - 编写一个玩具编译器 - 调用是段错误的
- javascript - 在javascript中获取div内部的值
- java - 是否可以在 SoapUI 中发布并稍后获取帖子正文?
- python - 参考线和折线的连续点之间的正交距离
- python-3.x - python readfile并根据匹配下的另一个行值匹配正则表达式
- raku - Apocalypse #1 中引入的“语义模型”是什么?