Skip to content

fix(android): defer startup camera change events - #4355

Open
RobJacobson wants to merge 4 commits into
rnmapbox:mainfrom
RobJacobson:codex/fix-4213-camera-event-tests
Open

RobJacobson wants to merge 4 commits into
rnmapbox:mainfrom
RobJacobson:codex/fix-4213-camera-event-tests

Conversation

@RobJacobson

@RobJacobson RobJacobson commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Description

Fixes #4213

Android may report a camera change before the map's attachment callbacks apply Camera.defaultSettings. Buffer startup notifications and dispatch one event from the current camera state after those callbacks complete. Subsequent camera changes continue to emit normally.

Reproducer evidence

Using the issue's configured center [-93.265, 44.9778]:

  • Before: startup events reported [0, 0], then [-93.265, 44.9778].
  • After: the startup event reported [-93.26500000000003, 44.9778]; no [0, 0] event was emitted.

Validation

This branch adds CameraChangeEventGateTest coverage for startup-change coalescing, normal changes after readiness, readiness without a pending change, and repeated readiness calls.

The end-to-end checks below were completed on the equivalent one-file implementation in PR #4348, before the gate was extracted into the helper used here. They were not rerun against this exact PR head. The checks used React Native 0.84.1, Mapbox Maps SDK 11.23.1, Fabric, and the Android example app; the issue report's React Native 0.83.6 and SDK 11.20.1 were not rerun.

  • Four launches emitted the configured initial center [-93.265, 44.9778] at zoom 6, with no initial [0, 0] callback.
  • Seven additional scenarios passed: empty style with defaults, valid defaults at [0, 0], map without a Camera, Camera without defaults, controlled camera props alongside defaults, later move to [0, 0], and later move to Tokyo.
  • Android example build and 11 native unit tests passed. yarn generate completed without generated changes, and yarn lint had no errors.
  • The full serial Jest rerun passed all 182 tests across 27 suites.

Checklist

  • I've read CONTRIBUTING.md.
  • I updated the doc/other generated code with running yarn generate in the root folder (not applicable to this native-only change).
  • I have tested the new feature on /example app.
    • In V11 mode/iOS
    • In New Architecture mode/iOS
    • In V11 mode/Android
    • In New Architecture mode/Android
  • I added/updated a sample - if a new feature was implemented (bug fix; no sample API added).

Screenshot OR Video

This is a native event timing fix; emulator logs above show the before/after behavior.

Component to reproduce the issue

<Mapbox.MapView
  style={{ flex: 1 }}
  onCameraChanged={(event) => {
    const [longitude, latitude] = event.properties.center;
    console.log(`COORDS ->> lng: ${longitude} lat: ${latitude}`);
  }}
>
  <Mapbox.Camera
    defaultSettings={{ centerCoordinate: [-93.265, 44.9778] }}
  />
</Mapbox.MapView>

- Hold startup camera notifications until attachment callbacks finish applying the initial camera
- Emit the current camera once after initialization and preserve subsequent camera events
- Keep maps without a Camera and valid zero-coordinate camera positions working
- Buffer startup camera notifications until camera setup is ready
- Coalesce startup notifications and preserve later camera changes
- Route native camera notifications through a focused readiness gate
- Dispatch the latest camera once attachment callbacks finish
- Verify startup notifications coalesce until camera setup is ready
- Verify subsequent notifications and empty startup behave correctly

@mfazekas mfazekas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this fixes #4213; we verified it on an emulator, including no-Camera, delayed Camera, re-attach and pans during startup. Splitting this out of RNMBXMapView makes sense, but a separate file and test for two flags is more than it needs; please make it a private anonymous object in RNMBXMapView (private val startupCameraEvents = object { … } calling sendCameraChangedEvents() directly) and drop CameraChangeEventGate.kt and its test. Please also shorten the attach comment to one line, e.g. // Camera.addToMap applies defaultSettings in the attach callbacks (#4213).

This branch was successfully deployed

1 active deployment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Android: onCameraChanged fires with [0,0] on launch

2 participants