android - 当有一个值被传递给 .onNext 时,RxJava Observable.create 返回 null
问题描述
我正在通过来自 google calendar V3 Java API 的 ID 获取日历事件,该 API 是以下内容的包装: https ://developers.google.com/calendar/v3/reference/events/get?apix_params=%7B%22calendarId%22 %3A%22primary%22%2C%22eventId%22%3A%226msto66us6ou1ri503lem4absk%22%7D
当我调用事件时,我将它包装在 Observable 中并将其传递给映射它的服务,然后通过活动调用该服务。
我遇到的一个问题是,当我启动新的 Observable 并调用事件时,事件被返回,但随后作为 null 传递给 Observable.next,这导致我的应用程序崩溃。当我调试时,我可以看到日历事件,所以我觉得这是一些奇怪的异步/线程问题。
以下是此次活动的呼吁:
@Module
class GoogleCalendarsApiServiceModule @Inject constructor(): IGoogleCalendarsApiServiceModule {
private lateinit var googleCalendarService: Calendar
private val httpTransport: NetHttpTransport = NetHttpTransport()
private val subscriptions: Disposable = Disposable.empty()
init {
this.subscriptions.apply {
AndroidContextObservable.context()
.subscribe { context ->
val googleCredential = GoogleCredentialsBuilder.getCredentials(httpTransport, context)
googleCalendarService = ServiceBuilder.buildGoogleCalendarService(googleCredential, httpTransport)
}
}
}
fun finalize() {
this.subscriptions.dispose()
}
override fun getEventById(eventId: String): Observable<Event> {
return Observable.create { observer ->
val calendarEvents: Calendar.Events? = googleCalendarService.events()
val event = calendarEvents!!
.get("primary", eventId)
.execute()
observer.onNext(event)
observer.onComplete()
}
}
}
然后映射事件的调用服务:
override fun getCalendarEventById(eventId: String): Observable<FullMeetingEvent> {
return this.googleCalendarsApiServiceModule.getEventById(eventId)
.map { mapMeetingEvent(it) } // <-- skipped due to event being null/empty runnable
.onErrorReturn { throw Exception(it) }
}
最后是调用活动:
class ViewMeetingEventDataActivity: AppCompatActivity() {
@Inject lateinit var bundleUtilityModule: BundleUtilityModule
@Inject lateinit var fragmentUtilityModule: FragmentUtilityModule
@Inject lateinit var googleCalendarService: GoogleCalendarService
private val subscriptions: Disposable = Disposable.empty()
private lateinit var eventId: String
private lateinit var event: FullMeetingEvent
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidContextObservable.setContext(this)
DaggerServiceModuleComponent.create().inject(this)
DaggerUtilityModuleComponent.create().inject(this)
this.eventId = intent.getStringExtra(BundleData.MEETING_EVENT_ID.name)!!
setContentView(R.layout.layout_view_meeting_event_activity)
}
override fun onStart() {
super.onStart()
subscriptions.apply {
googleCalendarService.getCalendarEventById(eventId)
.subscribeOn(Schedulers.io())
.subscribe(
{
event = it
setViewMeetingEventFragment(it)
},
{err -> println(err)}
)
}
}
override fun onDestroy() {
super.onDestroy()
this.subscriptions.dispose()
}
private fun setViewMeetingEventFragment(meetingEvent: FullMeetingEvent) {
fragmentUtilityModule.createSingleFragment<FullMeetingEvent, ViewMeetingEventDataFragment>(meetingEvent, BundleData.FULL_MEETING_EVENT.name, supportFragmentManager, R.id.view_meeting_event_data_container)
}
}
显然,随着服务失败,活动中的订阅直接进入错误块。
我知道我有这个事件,在调试器中四处挖掘时,我设法找到了它:
但正如您在调试器上方的代码中看到的那样,它显然是在创建一个 null observable。
这就像 observable 在事件调用完成之前已经触发,但我有代码以完全相同的方式抓取我的所有事件并且它工作得很好。
解决方案
事实证明,该服务正在吞噬错误并将 s**t 推回 Activity。实际错误来自映射器并试图使用为空的东西。修复方法是:
fun mapMeetingEvent(googleCalendarEvent: Event): FullMeetingEvent {
val attendees = mutableListOf<String>()
var organiser: String;
if(googleCalendarEvent.attendees != null && googleCalendarEvent.attendees.size > 0) {
googleCalendarEvent.attendees.forEach { x ->
if(x.displayName != null) {
attendees.add(x.displayName)
}
else {
attendees.add(x.email)
}
}
}
if (googleCalendarEvent.organizer.displayName != null) {
organiser = googleCalendarEvent.organizer.displayName
} else {
organiser = "No organiser"
}
return FullMeetingEvent(
googleCalendarEvent.description,
googleCalendarEvent.summary,
googleCalendarEvent.id,
googleCalendarEvent.start.dateTime,
googleCalendarEvent.end.dateTime,
googleCalendarEvent.location,
attendees,
organiser
)
}
很遗憾必须像这样进行空值检查,但我想就是这样。
推荐阅读
- angular - 如何在angular10中将mat-table放在mat-expansion中
- powershell - 从 PowerShell 提示符执行命令的更简单方法
- docker - 当健康检查 url 指向自身时,Docker swarm 服务未启动
- python - 在 PostgreSQL 数据库中存储字节类型对象
- javascript - Chartjs:如何设置对数刻度的最大刻度数
- reactjs - React 17.0.2 功能组件仅在第一次渲染时播放 CSS 动画
- javascript - 如何让用户只用粗体/斜体/下划线突出显示的内容?
- javascript - 指示元素相互交叉
- python - 如何将 XDP 文件与 XFA PDF 合并(通过 Python)?
- python - 气流模板字段中的 if 语句