Await SDK calls

Prev Next

Starting with flutter_insider 5.5.0, the identity, in-app message, and App Cards tracking methods that used to be fire-and-forget return a Future. You can await a call before making the next one, so your calls run in order.

Two new identity methods, loginAsync and logoutResettingInsiderIDAsync, also resolve to the merged Insider ID. The native SDK and the data it sends do not change, and existing call sites keep compiling.

login and logoutResettingInsiderID keep their void signature and the optional insiderIDResult callback. The awaitable forms are the separate methods loginAsync and logoutResettingInsiderIDAsync.

This guide explains the following concepts:

Prerequisites

  • Insider Flutter Plugin flutter_insider: 5.5.0 or later

  • The SDK initialized with FlutterInsider.Instance.init(...) before you call any of the methods below


Identity methods live on the user object, App Cards tracking methods on the App Cards client, and the in-app message and deep link methods on the main SDK singleton.

import 'package:flutter_insider/flutter_insider.dart';
import 'package:flutter_insider/src/identifiers.dart';

final user = FlutterInsider.Instance.getCurrentUser();
final appCards = FlutterInsider.Instance.appCards;

FlutterInsiderIdentifiers is not re-exported by the main library. Import package:flutter_insider/src/identifiers.dart where you build identifiers. This is a temporary workaround until the class is exported from the main library.

getCurrentUser() returns null until init has been called. Guard it with ?. or check for null before you call an identity method.

Async model

Two kinds of methods became awaitable.

Kind

Return type

Completes when

Result

Tracking and lifecycle
logout, view, click, clickButton, disableInAppMessages, enableInAppMessages, handleUniversalLink

Future<void>

The native SDK call has returned

No value

Identity
loginAsync, logoutResettingInsiderIDAsync

Future<String?>

The native SDK has merged or reset the user, or timeout elapses

The Insider ID, or null

// Order two calls: the second starts after the first has reached the native SDK
await FlutterInsider.Instance.disableInAppMessages();
await FlutterInsider.Instance.enableInAppMessages();

// Wait for the merged Insider ID
final insiderID = await user.loginAsync(identifiers);

Timeout

loginAsync and logoutResettingInsiderIDAsync take a named timeout (default 10 seconds). The native SDK answers only after a successful merge or reset. If the device is offline, a request fails, or a retry is pending, the native SDK never calls back. The Future then resolves to null once timeout elapses.

  • A timeout does not cancel the native call. The merge can still complete afterward, and the SDK keeps the resulting Insider ID.

  • timeout must be positive. Raise it per call when you expect a slow network.

  • After a null, FlutterInsider.Instance.getInsiderID() returns the ID the SDK holds at that moment, which can still be the pre-merge ID. To be told when the merged ID arrives, register FlutterInsider.Instance.registerInsiderIDListener(...).

final insiderID = await user.loginAsync(
  identifiers,
  timeout: const Duration(seconds: 30),
);

Error handling

None of the methods on this page throw. App Cards retrieval methods such as getCampaigns still throw InsiderAppCardsException. See Configure app cards for details.

When a native call fails, the SDK reports the failure and the Future still completes. Future<void> methods complete normally, and the identity methods resolve to null. The SDK also reports a failure that arrives after the timeout.

Three cases resolve loginAsync and logoutResettingInsiderIDAsync to null. You cannot tell them apart from the return value:

Case

What happened

No ID delivered

The native SDK finished without an Insider ID. For loginAsync, this also happens when the identifier set is empty, and the call is not sent.

Native failure

The native call failed, and the SDK reported the failure.

Timeout

timeout elapsed before the native SDK answered. The call can still complete.

final insiderID = await user.loginAsync(identifiers);

if (insiderID == null) {
  // No ID, native failure, or timeout. The SDK can still merge the user later;
  // read the current ID when you need it.
  final currentID = await FlutterInsider.Instance.getInsiderID();
  print('Insider ID after login attempt: $currentID');
} else {
  print('Logged in as $insiderID');
}

Available methods

Identity

loginAsync

Identifies the user with one or more identifiers and resolves to the merged Insider ID. This is the awaitable form of login with insiderIDResult.

Name

Type

Required

Description

identifiers

FlutterInsiderIdentifiers

Yes

Email, phone number, user ID, or custom identifiers. An empty set is not sent and resolves to null.

timeout

Duration

No

How long to wait for the native SDK. Default: Duration(seconds: 10). Must be positive.

Signature:

Future<String?> loginAsync(
  FlutterInsiderIdentifiers identifiers, {
  Duration timeout = const Duration(seconds: 10),
})

Example:

final identifiers = FlutterInsiderIdentifiers()
  ..addEmail('user@example.com')
  ..addUserID('user-001');

final insiderID = await FlutterInsider.Instance.getCurrentUser()?.loginAsync(identifiers);
print('Insider ID: $insiderID');

Keep using login(identifiers, insiderIDResult: ...) when you want the callback style. loginAsync sends the same request as login with a callback.

logout

Logs the current user out and keeps the existing Insider ID.

Signature:

Future<void> logout()

Example:

await FlutterInsider.Instance.getCurrentUser()?.logout();

logoutResettingInsiderIDAsync

Logs the user out, resets the Insider ID, and resolves to the new one. This is the awaitable form of logoutResettingInsiderID with insiderIDResult.

Name

Type

Required

Description

additionalIdentifiers

List<FlutterInsiderIdentifiers>?

Yes

Identifiers attached to the new anonymous identity. Pass null for none.

timeout

Duration

No

How long to wait for the native SDK. Default: Duration(seconds: 10). Must be positive.

Signature:

Future<String?> logoutResettingInsiderIDAsync(
  List<FlutterInsiderIdentifiers>? additionalIdentifiers, {
  Duration timeout = const Duration(seconds: 10),
})

Example:

final newInsiderID = await FlutterInsider.Instance
    .getCurrentUser()
    ?.logoutResettingInsiderIDAsync(null);
print('New Insider ID: $newInsiderID');

disableInAppMessages

Suppresses in-app messages until you call enableInAppMessages.

Signature:

Future<void> disableInAppMessages()

Example:

await FlutterInsider.Instance.disableInAppMessages();

enableInAppMessages

Re-enables in-app messages after a previous disableInAppMessages call.

Signature:

Future<void> enableInAppMessages()

Example:

await FlutterInsider.Instance.disableInAppMessages();
// Show your own full-screen flow, then
await FlutterInsider.Instance.enableInAppMessages();

Lets the Insider SDK process a deep link or universal link. Call it from your link handler.

Name

Type

Required

Description

url

String

Yes

The link to hand to the SDK.

Signature:

Future<void> handleUniversalLink(String url)

Example:

await FlutterInsider.Instance.handleUniversalLink('https://example.com/campaign?ins=1');

App Cards tracking

The App Cards tracking methods return a Future<void> that completes when the native SDK call has returned. See Configure app cards for the card model and the retrieval methods.

Method

Signature

FlutterInsiderAppCards.view

Future<void> view(InsiderAppCard appCard)

FlutterInsiderAppCards.click

Future<void> click(InsiderAppCard appCard)

FlutterInsiderAppCards.clickButton

Future<void> clickButton(InsiderAppCardButton button)

InsiderAppCard.view

Future<void> view()

InsiderAppCard.click

Future<void> click()

InsiderAppCardButton.click

Future<void> click()

Example:

final appCards = FlutterInsider.Instance.appCards;

try {
  final response = await appCards.getCampaigns();
  for (final card in response?.appCards ?? <InsiderAppCard>[]) {
    await card.view();
  }
} on InsiderAppCardsException catch (e) {
  print('Failed to get campaigns: ${e.error.code}');
}

Migration notes

Call sites compile unchanged. A Future<void> returned from a method you used to call as void is dropped. Two things can change in your project:

  • Lint hits: With unawaited_futures or discarded_futures enabled, the linter reports every existing call to one of these methods. Either await the call or wrap it in unawaited(...) from dart:async.

  • Test doubles: A fake or mock that overrides one of these methods with a void body, or an unstubbed mock, now has to return a Future. Return Future.value() for Future<void>, and Future.value(null) or an ID string for Future<String?>.

To keep the fire-and-forget behavior explicitly, wrap the call in unawaited:

import 'dart:async';

// Keep the fire-and-forget behaviour explicitly
unawaited(FlutterInsider.Instance.handleUniversalLink(url));

Full integration example

The following example signs a user in and out. It keeps in-app messages away from the sign-in screen and handles a login that returns no Insider ID.

import 'package:flutter_insider/flutter_insider.dart';
import 'package:flutter_insider/src/identifiers.dart';

Future<void> signIn(String email, String userID) async {
  final user = FlutterInsider.Instance.getCurrentUser();
  if (user == null) {
    return;
  }

  // Keep in-app messages out of the way while the sign-in screen is up
  await FlutterInsider.Instance.disableInAppMessages();

  final identifiers = FlutterInsiderIdentifiers()
    ..addEmail(email)
    ..addUserID(userID);

  final insiderID = await user.loginAsync(
    identifiers,
    timeout: const Duration(seconds: 15),
  );

  if (insiderID == null) {
    final currentID = await FlutterInsider.Instance.getInsiderID();
    print('Login not confirmed; current Insider ID: $currentID');
  } else {
    print('Logged in as $insiderID');
  }

  // Resumes only after the native call has returned
  await FlutterInsider.Instance.enableInAppMessages();
}

Future<void> signOut() async {
  final user = FlutterInsider.Instance.getCurrentUser();
  if (user == null) {
    return;
  }

  final newInsiderID = await user.logoutResettingInsiderIDAsync(null);
  print('Anonymous Insider ID: $newInsiderID');
}

Awaiting SDK calls lets you run Flutter SDK calls in order and read the merged Insider ID when a login or logout finishes. For the individual methods, see the user object, block in-app messages, handle universal links, and configure app cards pages.