Repository navigation
[SDK-791] Display in-app messages on the main thread when showMessage is called off it - #1102
joaodordio wants to merge 3 commits into
Conversation
… is called off it Since 3.9.0 the Dialog renderer registers a LifecycleRegistry observer, which throws off the main thread. Post the display to the main looper, matching the iOS SDK. Main-thread callers are unchanged.
| } | ||
|
|
||
| public void showMessage(final @NonNull IterableInAppMessage message, boolean consume, final @Nullable IterableHelper.IterableUrlCallback clickCallback, @NonNull IterableInAppLocation inAppLocation) { | ||
| public void showMessage(final @NonNull IterableInAppMessage message, final boolean consume, final @Nullable IterableHelper.IterableUrlCallback clickCallback, final @NonNull IterableInAppLocation inAppLocation) { |
There was a problem hiding this comment.
~L252–254 and ~L268: Threading Javadoc is missing on two public overloads
What the spec says: SDK-791 acceptance criteria: “Javadoc on showMessage states the threading behaviour.” The work item names the 4-argument overload as the method that changes.
Why it conflicts: Callers of showMessage(message, location) and showMessage(message, consume, clickCallback, location) do not see the new contract on the method they invoke. The documented overloads do state it, so the checkbox is met for those entry points.
Suggested action: Add the same threading sentence to the location overload and the 4-argument overload.
franco-zalamena-iterable
left a comment
There was a problem hiding this comment.
I have one last "anti-flakiness" suggestion in a separate branch, will send you to you, for now there are only small suggestions
…ppManager.java Co-authored-by: Franco Zalamena <franco.zalamena@iterable.com>
📝 Summary
IterableInAppManager.showMessageis now safe to call from any thread: off the main thread it posts the display to the main looper.🎟️ Jira Ticket: SDK-791
📖 Description
Root cause behind SDK-789 (HelloFresh, RN 3.2.0 on native 3.10.1).
showMessagecalledIterableInAppDisplayer.showMessageon the caller thread. Since 3.9.0 (SDK-100), a host activity that is not aFragmentActivitytakes the Dialog path, andIterableInAppDialogNotification.createInstancecallsLifecycleRegistry.addObserver, which throwsIllegalStateException: Method addObserver must be called on the main thread. Before 3.9.0 that host was a silent no-op, and the Fragment path only posts throughFragmentTransaction.commit(), which is why calling from a background thread was latent for years.iOS already guarantees this:
InAppManager.show(message:consume:callback:)always dispatches to main ("This is public, so make sure we call from Main Thread").Change:
showMessageoverload (all public overloads andprocessMessagesfunnel into it) posts itself to the main looper when called off it, using the samenew Handler(Looper.getMainLooper()).postpattern asnotifyOnChange.setReadandmarkForDeletionstill run synchronously.The React Native bridge also hops in react-native-sdk#918 so RN 3.2.1 is fixed without waiting on this release. This PR protects native and Flutter callers.
🧪 How to test?
New
IterableInAppManagerThreadingTest(Robolectric, realComponentActivityhost, real displayer):showMessagefrom a backgroundHandlerThread(same shape as the RN native-modules thread) does not throw, does not display until the main looper runs, then displays the Dialog.showMessagefrom the main thread displays synchronously.With the hop removed, the background test fails with the production exception:
IllegalStateException: Method addObserver must be called on the main thread.Local results:
IterableInAppManagerTest,IterableInAppManagerSyncTest,IterableInAppDialogNotificationTest,IterableInAppHTMLNotificationTest, new threading test): 90 tests, 0 failures, 3 pre-existing@Ignore.:iterableapi:testDebugUnitTest: 793 tests, 1 failure inIterableAsyncInitializationTest.testOperationQueuing_LargeNumberOfOperations. That test does not touch the in-app manager and passes 3/3 in isolation on this branch and onmaster; it is a pre-existing flake under full-suite load (5 s init wait).checkstylepasses.🧾 Changelog
Added under
[Unreleased] > Fixed.📚 Docs PR if applicable
No public docs describe
showMessagethreading today; the Javadoc now does.