Rx Java Observable.create возвращает ноль, когда значение передается в .onNext - PullRequest
0 голосов
/ 16 апреля 2020

Я получаю событие календаря по идентификатору из API Google V3 Java календаря, который является оберткой: 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 и вызываю событие, Событие возвращается, но затем передается в 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)
    }
}

Очевидно, что при сбое службы подписка в действии переходит прямо к блоку ошибок.

Я знаю, что у меня есть событие, покопавшись в отладчике, мне удалось его найти:

enter image description here

Но как вы можно увидеть в коде выше отладчика, он явно создает нулевую наблюдаемую.

Это похоже на то, что наблюдаемое сработало до того, как завершился вызов события, но у меня есть код, который точно так же захватывает все мои события, и он прекрасно работает.

1 Ответ

0 голосов
/ 16 апреля 2020

Оказывается, что служба поглотила ошибку и вернула 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
        )
    }

Обидно, что проверка нуля должна выполняться так, но я думаю, что так оно и есть.

...