Skip to content

Commit 52e1059

Browse files
fix(sample): gate deferred-init to Android and make startMParticle idempotent
Addresses review feedback: - index.js: only run the first-frame DeferredInit call on Android, so iOS no longer logs a spurious 'module not available' warning every launch. - DeferredInitModule: short-circuit startMParticle() when MParticle is already started, so repeat JS calls (Fast Refresh / remounts) don't double-register lifecycle callbacks or re-start the SDK. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent f5e04be commit 52e1059

2 files changed

Lines changed: 27 additions & 16 deletions

File tree

sample/android/app/src/main/java/com/mparticlesample/DeferredInitModule.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ class DeferredInitModule(private val reactContext: ReactApplicationContext) :
6868
return
6969
}
7070

71+
// Idempotent: JS may invoke this more than once (Fast Refresh, remounts). Once mParticle
72+
// has started, skip re-registering the lifecycle observer and re-starting the SDK.
73+
if (MParticle.getInstance() != null) {
74+
promise.resolve("already started")
75+
return
76+
}
77+
7178
Log.i(TAG, "startMParticle() called from JS (post first-frame). MParticle.getInstance()=${MParticle.getInstance()}")
7279

7380
val app = reactContext.applicationContext as Application

sample/index.js

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -171,22 +171,26 @@ export default class MParticleSample extends Component {
171171
}
172172

173173
componentDidMount() {
174-
// Deferred-init edge-case example (Android). When DeferredInitModule.DEFERRED_INIT_EXAMPLE
175-
// is enabled, mParticle is started from the native module at the moment the first frame is
176-
// painted, instead of in MainApplication.onCreate(). requestAnimationFrame fires after the
177-
// first frame is committed -- by which point MainActivity has already RESUMED, which is what
178-
// triggers the Rokt overlay Activity-capture race. When the flag is off (default) this is a
179-
// no-op. See DeferredInitModule.kt for the full explanation.
180-
requestAnimationFrame(() => {
181-
const {DeferredInit} = NativeModules;
182-
if (DeferredInit) {
183-
DeferredInit.startMParticle()
184-
.then(r => console.log('Deferred MParticle.start ->', r))
185-
.catch(e => console.warn('Deferred start failed', e));
186-
} else {
187-
console.warn('DeferredInit native module not available');
188-
}
189-
});
174+
// Deferred-init edge-case example (Android only). The DeferredInit native module exists only
175+
// on Android; iOS resolves the presenter lazily and is unaffected, so we skip it there to keep
176+
// iOS quiet. When DeferredInitModule.DEFERRED_INIT_EXAMPLE is enabled, mParticle is started
177+
// from the native module at the moment the first frame is painted, instead of in
178+
// MainApplication.onCreate(). requestAnimationFrame fires after the first frame is committed --
179+
// by which point MainActivity has already RESUMED, which is what triggers the Rokt overlay
180+
// Activity-capture race. When the flag is off (default) this is a no-op on the native side.
181+
// See DeferredInitModule.kt for the full explanation.
182+
if (Platform.OS === 'android') {
183+
requestAnimationFrame(() => {
184+
const {DeferredInit} = NativeModules;
185+
if (DeferredInit) {
186+
DeferredInit.startMParticle()
187+
.then(r => console.log('Deferred MParticle.start ->', r))
188+
.catch(e => console.warn('Deferred start failed', e));
189+
} else {
190+
console.warn('DeferredInit native module not available');
191+
}
192+
});
193+
}
190194

191195
MParticle.getSession(session => this.setState({session}));
192196

0 commit comments

Comments
 (0)