Android Kotlin RxJava 改造 - 空 DisposableObserver LiveData
Android Kotlin RxJava Retrofit - empty DisposableObserver LiveData
我正在 Kotlin 中实现一个 Android 应用程序,它使用 API 作为数据的主要来源。我使用 Kotlin、RXjava、Retrofit 和 Dagger 来让它工作。
但由于某种原因,我的 person 对象在 onNext 函数中为空。尽管我在 Logcat 中看到了 http 方法调用数据,并且它具有正确的人员对象。
我正在请求来自 JSON 的人物对象:
{
"persons": [{
"personId": 1,
"personName": "Bert",
"personAge": 19,
"isFemale": "false",
"birthDate": "2000-06-28T00:00:00"
}
]
}
Api接口:
@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 调用 returns 我可以在日志中看到的正确的人,但它并不像我想要的那样 post personResult 中的值。不知道为什么。
编辑:根据要求添加了人物 class。请注意,@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 响应与要使用的实际对象之间的不匹配,定义一个中间 class 像这样的东西:
data class PersonResponse(
@Json(name = "persons")
val persons: List<Person>
)
示例 api class:
@GET("persons")
fun getPerson(@Query("personId") personId: Int): Observable<PersonResponse>
@GET("persons")
fun getAllPersons(): Observable<PersonResponse>
示例存储库 class:
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 class 和存储库 class 之间建立一个中间层,它完成所有的转换。
我正在 Kotlin 中实现一个 Android 应用程序,它使用 API 作为数据的主要来源。我使用 Kotlin、RXjava、Retrofit 和 Dagger 来让它工作。
但由于某种原因,我的 person 对象在 onNext 函数中为空。尽管我在 Logcat 中看到了 http 方法调用数据,并且它具有正确的人员对象。
我正在请求来自 JSON 的人物对象:
{
"persons": [{
"personId": 1,
"personName": "Bert",
"personAge": 19,
"isFemale": "false",
"birthDate": "2000-06-28T00:00:00"
}
]
}
Api接口:
@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 调用 returns 我可以在日志中看到的正确的人,但它并不像我想要的那样 post personResult 中的值。不知道为什么。
编辑:根据要求添加了人物 class。请注意,@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 响应与要使用的实际对象之间的不匹配,定义一个中间 class 像这样的东西:
data class PersonResponse(
@Json(name = "persons")
val persons: List<Person>
)
示例 api class:
@GET("persons")
fun getPerson(@Query("personId") personId: Int): Observable<PersonResponse>
@GET("persons")
fun getAllPersons(): Observable<PersonResponse>
示例存储库 class:
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 class 和存储库 class 之间建立一个中间层,它完成所有的转换。