Skip to content

Preload Plan

Preload plans in advance and reuse them later without the internet during the app lifecycle.

Overview

  • Use ExpoFpPlan.preloader to preload plans.
  • A preloaded plan is represented by ExpoFpPreloadedPlanInfo.
  • You can obtain a presenter for a preloaded plan with getPreloadedPlanPresenter(...).
  • Recommended: Preload plans if you expect to reuse them multiple times in one session.
  • If a preloaded plan is reloaded with a new planLink, the link info is automatically updated in the stored ExpoFpPreloadedPlanInfo.

Lifecycle Management

Important: Preloaded plans are NOT automatically disposed when the Activity/Fragment is destroyed. This allows you to reuse the same presenter across multiple screens without reloading.

  • Preloaded plans persist in memory until you explicitly call disposePreloadedPlan() or removeAllPreloadedPlans().
  • You can safely attach and detach the same preloaded presenter to different Activities/Fragments.
  • All event callbacks will continue to work after reattaching a preloaded plan.
  • You are responsible for disposing preloaded plans when they are no longer needed to free memory.

Step 1. Preload from the Internet

val expoKey = "YourExpoKey"

val preloadedPlanInfo = ExpoFpPlan.preloader.preloadPlan(
    planLink = ExpoFpLinkType.ExpoKey(expoKey)
)

With additional parameters

val additionalParams = listOf(ExpoFpPlanParameter.NoOverlay(true), ExpoFpPlanParameter.HideHeaderLogo(true))
val locationProvider: IExpoFpLocationProvider = YourLocationProvider()
val messageListener: IExpoFpPlanMessageListener = YourMessageListener()

val preloadedPlanInfo = ExpoFpPlan.preloader.preloadPlan(
    planLink = ExpoFpLinkType.ExpoKey("YourExpoKey"),
    additionalParams = additionalParams,
    locationProvider = locationProvider,
    messageListener = messageListener
)

Step 2. Preload from Downloaded Plan

val preloadedPlanInfo = ExpoFpPlan.preloader.preloadPlan(
    planLink = ExpoFpLinkType.DownloadedPlanInfo(downloadedPlanInfo)
)

With additional parameters

val additionalParams = listOf(ExpoFpPlanParameter.NoOverlay(true), ExpoFpPlanParameter.HideHeaderLogo(true))
val locationProvider: IExpoFpLocationProvider = YourLocationProvider()
val messageListener: IExpoFpPlanMessageListener = YourMessageListener()

val preloadedPlanInfo = ExpoFpPlan.preloader.preloadPlan(
    planLink = ExpoFpLinkType.DownloadedPlanInfo(downloadedPlanInfo),
    additionalParams = additionalParams,
    locationProvider = locationProvider,
    messageListener = messageListener
)

Step 3. Manage Preloaded Plans

Get all preloaded plans:

val preloadedPlansInfo: List<ExpoFpPreloadedPlanInfo> =
    ExpoFpPlan.preloader.getPreloadedPlansInfo()

Get a presenter from a preloaded plan:

val presenter = ExpoFpPlan.preloader.getPreloadedPlanPresenter(preloadedPlanInfo)

If only one plan is preloaded, you can get it without parameters:

val presenter = ExpoFpPlan.preloader.getPreloadedPlanPresenter()


Step 4. Show Preloaded Plan

View-based UI

val planView = presenter.getView()

// IMPORTANT: If reusing a preloaded plan, remove from old parent first
(planView.parent as? ViewGroup)?.removeView(planView)

container.addView(planView)

Note: When reusing a preloaded plan across multiple screens, always remove the view from its old parent before adding it to a new container. Otherwise, you'll get an IllegalStateException: The specified child already has a parent.

Jetpack Compose

AndroidView(
    factory = {
        presenter.getView().apply {
            // Remove from old parent if reusing
            (parent as? ViewGroup)?.removeView(this)
        }
    }
)

Step 5. Delete Preloaded Plans

Delete a specific plan:

val presenter = ExpoFpPlan.preloader.disposePreloadedPlan(preloadedPlanInfo)

Delete all plans:

ExpoFpPlan.preloader.removeAllPreloadedPlans()


Best Practices

  • Preload early: Preload plans during app initialization or screen preparation if you expect repeated access.
  • Reuse presenters: Get presenters from preloaded plans instead of creating new ones to reduce loading time.
  • Clear when not needed: Dispose preloaded plans when they are no longer needed to free memory.
  • Combine with download: Download plans to disk first, then preload them for faster reuse.

Memory Management

Preloaded plans remain in memory until explicitly disposed:

class MainActivity : AppCompatActivity() {
    private var preloadedPlanInfo: ExpoFpPreloadedPlanInfo? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Preload plan once
        if (preloadedPlanInfo == null) {
            preloadedPlanInfo = ExpoFpPlan.preloader.preloadPlan(
                planLink = ExpoFpLinkType.ExpoKey("demo")
            )
        }

        // Get presenter from preloaded plan
        val presenter = ExpoFpPlan.preloader.getPreloadedPlanPresenter(preloadedPlanInfo)

        // Attach to view - can be done multiple times across different Activities
        presenter?.let {
            val planView = it.getView()
            container.addView(planView)
        }
    }

    override fun onDestroy() {
        super.onDestroy()

        // Only dispose when you no longer need the plan
        if (isFinishing) {
            preloadedPlanInfo?.let {
                ExpoFpPlan.preloader.disposePreloadedPlan(it)
            }
        }
    }
}

Reusing Across Multiple Screens

Preloaded plans can be safely reused across different Activities or Fragments:

// Activity A
class MapActivityA : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val presenter = ExpoFpPlan.preloader.getPreloadedPlanPresenter(preloadedPlanInfo)

        // Get the view from presenter
        val planView = presenter?.getView()

        // IMPORTANT: Remove from old parent if it was attached before
        (planView?.parent as? ViewGroup)?.removeView(planView)

        // Now add to this activity's container
        container.addView(planView)

        // Set message listener for this screen
        presenter?.setMessageListener(myListener)
    }

    // Activity A is destroyed, but plan stays in memory
}

// Activity B - reuse the same preloaded plan
class MapActivityB : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Get the same presenter - no reloading needed!
        val presenter = ExpoFpPlan.preloader.getPreloadedPlanPresenter(preloadedPlanInfo)

        // Get the view from presenter
        val planView = presenter?.getView()

        // IMPORTANT: Remove from old parent (Activity A's container) before adding here
        (planView?.parent as? ViewGroup)?.removeView(planView)

        // Now add to this activity's container
        container.addView(planView)

        // All callbacks still work
        presenter?.setMessageListener(myListener)
    }
}