简体   繁体   English

Android Kotlin RxJava改造-空的DisposableObserver LiveData

[英]Android Kotlin RxJava Retrofit - empty DisposableObserver LiveData

I'm implementing an Android application in Kotlin that uses an API as it's primary source for data. 我正在Kotlin中实现一个Android应用程序,该应用程序使用API​​作为数据的主要来源。 I use Kotlin, RXjava, Retrofit and Dagger to make it work. 我使用Kotlin,RXjava,Retrofit和Dagger使其工作。

But for some reason my person object at the onNext function is empty. 但是由于某种原因,我在onNext函数上的人员对象为空。 Even though I see the http method call data in the Logcat, and it has the correct person object. 即使我在Logcat中看到http方法调用数据,它也具有正确的person对象。

I'm requesting a person object from JSON: 我从JSON请求一个person对象:

{
  "persons": [{
      "personId": 1,
      "personName": "Bert",
      "personAge": 19,
      "isFemale": "false",
      "birthDate": "2000-06-28T00:00:00"
    }
  ]
}

ApiInterface: ApiInterface:

@GET("persons")
fun getPerson(@Query("personId") personId: Int): Observable<Person>

PersonRepository: PersonRepository:

class PersonRepository @Inject constructor(val apiInterface: ApiInterface) {
  fun getPerson(personId: Int): Observable<Person>{
    return apiInterface.getPerson(personId)
  }
}

Person ViewModel: 人员视图模型:

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 where the call is made: 进行呼叫的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
 }
}

The getPerson call returns the correct person which I can see in the logs, but it doesn't post the value in personResult, like I want. getPerson调用返回的是我可以在日志中看到的正确人员,但是它没有像我想要的那样将值发布到personResult中。 I don't know why. 我不知道为什么

Edit: Added the Person class as requested. 编辑:根据要求添加了Person类。 Note that @Json is the Moshi equivalent of @SerializedName from GSON. 请注意,@ Json与GSON中的@SerializedName等效。

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

)

To avoid mismatch between the JSON response and the actual object to be used, define a intermediate class something like this: 为了避免JSON响应和要使用的实际对象之间的不匹配,请定义一个中间类,如下所示:

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

Example api class: api类示例:

@GET("persons")
fun getPerson(@Query("personId") personId: Int): Observable<PersonResponse>    

@GET("persons")
fun getAllPersons(): Observable<PersonResponse>

Example repository 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 }
}

As you can see repository code can look quite messy. 如您所见,存储库代码看起来很混乱。 I suggest making an intermediate layer between your api class and repository class which does all the conversions. 我建议在您的api类和存储库类之间做一个中间层,以完成所有转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM