Skip to content

Hosts

A screen host owns a Reconciler, schedules re-renders, and forwards platform lifecycle events (resume, pause, back press, destroy) to navigators and effects. It's also the HostNavigator a root Stack.Navigator talks to when it pushes real native screens.

The bundled Android (ScreenFragment) and iOS (ViewController) templates create a host via create_screen and never need to be edited by app code. The desktop preview uses DesktopScreenHost.

Screen hosts: the bridge between a native screen and the reconciler.

Native templates create one host per screen:

host = pythonnative.hosts.create_screen("app.main", native_instance, args_json)
host.on_create()

and forward lifecycle events to it. The concrete class depends on the runtime (AndroidScreenHost, IOSScreenHost, DesktopScreenHost); the headless base ScreenHost is used in unit tests with a fake backend.

Modules:

Name Description
android

Android screen host: a fragment inside the template's NavHostFragment.

base

Platform-independent screen host.

desktop

Desktop preview host (Tkinter), driven by pn preview.

ios

iOS screen host: one UIViewController per screen, driven by ViewController.swift.

Classes:

Name Description
ScreenHost

Base screen host; see the module docstring.

Functions:

Name Description
import_component

Import a root component by module path or dotted attribute path.

host_class

The host class for the current runtime.

create_screen

Create the screen host for a root component.

ScreenHost

ScreenHost(
    native_instance: Any,
    component_path: str,
    component: Any,
)

Base screen host; see the module docstring.

Attributes:

Name Type Description
native_instance

The platform object owning this screen (Activity, UIViewController, DesktopApp).

component_path

Import path of the root component.

args Dict[str, Any]

Launch arguments (set_args), including the serialized navigation state under "pn_nav" for pushed screens.

reconciler Any

The mounted reconciler, or None before on_create / after on_destroy.

is_focused

Whether the screen is presented (on_resume / on_pause).

Methods:

Name Description
initial_navigation_state

Return the serialized navigation state from args["pn_nav"], or None for the first screen.

push_screen

Push a native screen running the same root component, seeded with state.

pop_screens

Pop count native screens (at least one).

replace_screen

Replace the current native screen with one seeded with state.

reset_screens

Rebuild the native stack for state.

set_screen_options

Apply header options (title and friends) to the native chrome.

add_focus_listener

Subscribe to focus changes (on_resume / on_pause); returns an unsubscribe callable.

on_create

Mount the root component (idempotent across native view recreation).

on_start

Handle the platform's start event (no-op by default).

on_resume

Mark the screen focused and notify focus listeners.

on_layout

Handle a native layout pass (no-op by default; platforms sync the viewport here).

on_pause

Mark the screen unfocused and notify focus listeners.

on_stop

Handle the platform's stop event (no-op by default).

on_restart

Handle the platform's restart event (no-op by default).

on_save_instance_state

Handle the platform's save-state request (no-op by default).

on_restore_instance_state

Handle the platform's restore-state event (no-op by default).

on_destroy

Tear down: unmount (running effect cleanups), release native views.

on_back_pressed

Offer the system back action to use_back_handler subscribers.

set_args

Record launch arguments (a dict or a JSON string).

set_focused

Update is_focused and notify focus listeners when the value changes.

set_viewport_size

Forward a viewport-size change (in points) to the reconciler.

request_render

Request a render pass (queued if one is in progress).

flush_scheduled_render

Run a render deferred by _schedule_render_async (platform UI turn).

show_redbox

Mount the dev error overlay over this screen (from any thread).

clear_redbox

Dismiss the dev error overlay, reattaching the app's root view unless reattach is False.

enable_hot_reload

Start polling manifest_path for reloads (see hot_reload_tick) and switch on dev mode.

hot_reload_tick

Poll the reload manifest; returns whether a reload was applied.

reload

Reload modules and refresh the tree (Fast Refresh, else full remount).

initial_navigation_state

initial_navigation_state() -> Optional[Dict[str, Any]]

Return the serialized navigation state from args["pn_nav"], or None for the first screen.

push_screen

push_screen(
    state: Dict[str, Any], options: Dict[str, Any]
) -> None

Push a native screen running the same root component, seeded with state.

pop_screens

pop_screens(count: int) -> None

Pop count native screens (at least one).

replace_screen

replace_screen(
    state: Dict[str, Any], options: Dict[str, Any]
) -> None

Replace the current native screen with one seeded with state.

reset_screens

reset_screens(
    state: Dict[str, Any], options: Dict[str, Any]
) -> None

Rebuild the native stack for state.

The root native screen stays; every route above the first gets its own native screen carrying the history up to it, so the back button walks the new stack.

set_screen_options

set_screen_options(options: Dict[str, Any]) -> None

Apply header options (title and friends) to the native chrome.

add_focus_listener

add_focus_listener(
    callback: Callable[[bool], None],
) -> Callable[[], None]

Subscribe to focus changes (on_resume / on_pause); returns an unsubscribe callable.

on_create

on_create() -> None

Mount the root component (idempotent across native view recreation).

Android destroys and recreates a fragment's view when the user pops back to it and calls on_create again; the Python host persists, so an already-mounted tree is simply re-attached.

on_start

on_start() -> None

Handle the platform's start event (no-op by default).

on_resume

on_resume() -> None

Mark the screen focused and notify focus listeners.

on_layout

on_layout() -> None

Handle a native layout pass (no-op by default; platforms sync the viewport here).

on_pause

on_pause() -> None

Mark the screen unfocused and notify focus listeners.

on_stop

on_stop() -> None

Handle the platform's stop event (no-op by default).

on_restart

on_restart() -> None

Handle the platform's restart event (no-op by default).

on_save_instance_state

on_save_instance_state() -> None

Handle the platform's save-state request (no-op by default).

on_restore_instance_state

on_restore_instance_state() -> None

Handle the platform's restore-state event (no-op by default).

on_destroy

on_destroy() -> None

Tear down: unmount (running effect cleanups), release native views.

on_back_pressed

on_back_pressed() -> bool

Offer the system back action to use_back_handler subscribers.

Returns True when a handler consumed the event, in which case the platform must not pop the screen.

set_args

set_args(args: Any) -> None

Record launch arguments (a dict or a JSON string).

set_focused

set_focused(focused: bool) -> None

Update is_focused and notify focus listeners when the value changes.

set_viewport_size

set_viewport_size(width: float, height: float) -> None

Forward a viewport-size change (in points) to the reconciler.

request_render

request_render() -> None

Request a render pass (queued if one is in progress).

flush_scheduled_render

flush_scheduled_render() -> None

Run a render deferred by _schedule_render_async (platform UI turn).

show_redbox

show_redbox(
    exc: BaseException, phase: str = "render"
) -> None

Mount the dev error overlay over this screen (from any thread).

clear_redbox

clear_redbox(reattach: bool = True) -> None

Dismiss the dev error overlay, reattaching the app's root view unless reattach is False.

enable_hot_reload

enable_hot_reload(
    manifest_path: str, source_root: Optional[str] = None
) -> None

Start polling manifest_path for reloads (see hot_reload_tick) and switch on dev mode.

source_root is accepted for the native templates, which pass the dev directory alongside the manifest; the reloader derives module paths from the manifest itself, so it is currently unused.

hot_reload_tick

hot_reload_tick() -> bool

Poll the reload manifest; returns whether a reload was applied.

reload

reload(
    changed_modules: Optional[Sequence[str]] = None,
) -> None

Reload modules and refresh the tree (Fast Refresh, else full remount).

import_component

import_component(component_path: str) -> Any

Import a root component by module path or dotted attribute path.

"app.main" imports the module and returns its App attribute; "app.main.RootScreen" returns the named attribute. Errors raised inside a resolvable module (a missing third-party dependency, a syntax error) propagate unchanged so the real cause stays visible.

Raises:

Type Description
ImportError

When neither form resolves.

host_class

host_class() -> Type[ScreenHost]

The host class for the current runtime.

create_screen

create_screen(
    component_path: str,
    native_instance: Any = None,
    args_json: Optional[str] = None,
) -> ScreenHost

Create the screen host for a root component.

Parameters:

Name Type Description Default
component_path str

"app.main" (the module's App is used) or a dotted path like "app.main.RootScreen". Imported lazily so the dev server can reload it.

required
native_instance Any

The platform object owning the screen (Activity, UIViewController pointer, DesktopApp).

None
args_json Optional[str]

Optional JSON launch arguments (pushed screens receive their navigation history here).

None

Returns:

Type Description
ScreenHost

A host ready for on_create and the other lifecycle calls.

drain_ios_scheduled_renders

drain_ios_scheduled_renders() -> None

Drain deferred iOS renders (called by the Swift template on the main thread).

forward_lifecycle

forward_lifecycle(native_addr: int, event: str) -> None

Forward a Swift view-controller lifecycle event to its host.

drain_desktop_scheduled_renders

drain_desktop_scheduled_renders() -> None

Drain deferred desktop renders (called by the preview's Tk loop).

Shared host logic

Platform-independent screen host.

A host bridges one native screen (an Android fragment, an iOS view controller, a desktop preview page) to a Reconciler rendering the app's root component. It owns:

  • Lifecycle: on_create mounts the tree, on_resume / on_pause track focus, on_destroy unmounts.
  • Render scheduling: state changes during a render are queued and drained in bounded batches; platforms hop off-main-thread requests onto the UI thread.
  • Navigation bridging: the host implements HostNavigator, so a root Stack.Navigator can push real native screens. Each pushed screen runs the same root component with its navigation history in args["pn_nav"].
  • Dev tooling: the RedBox error overlay and hot reload (Fast Refresh with a full-remount fallback).

Subclasses implement the handful of _native_* primitives for their platform (attach a root view, push a screen, set the title, ...).

Classes:

Name Description
ScreenHost

Base screen host; see the module docstring.

Functions:

Name Description
debug_enabled

Return whether the PYTHONNATIVE_DEBUG environment variable turns on host diagnostics.

log_pn

Emit optional diagnostics when PYTHONNATIVE_DEBUG is enabled.

import_component

Import a root component by module path or dotted attribute path.

ScreenHost

ScreenHost(
    native_instance: Any,
    component_path: str,
    component: Any,
)

Base screen host; see the module docstring.

Attributes:

Name Type Description
native_instance

The platform object owning this screen (Activity, UIViewController, DesktopApp).

component_path

Import path of the root component.

args Dict[str, Any]

Launch arguments (set_args), including the serialized navigation state under "pn_nav" for pushed screens.

reconciler Any

The mounted reconciler, or None before on_create / after on_destroy.

is_focused

Whether the screen is presented (on_resume / on_pause).

Methods:

Name Description
initial_navigation_state

Return the serialized navigation state from args["pn_nav"], or None for the first screen.

push_screen

Push a native screen running the same root component, seeded with state.

pop_screens

Pop count native screens (at least one).

replace_screen

Replace the current native screen with one seeded with state.

reset_screens

Rebuild the native stack for state.

set_screen_options

Apply header options (title and friends) to the native chrome.

add_focus_listener

Subscribe to focus changes (on_resume / on_pause); returns an unsubscribe callable.

on_create

Mount the root component (idempotent across native view recreation).

on_start

Handle the platform's start event (no-op by default).

on_resume

Mark the screen focused and notify focus listeners.

on_layout

Handle a native layout pass (no-op by default; platforms sync the viewport here).

on_pause

Mark the screen unfocused and notify focus listeners.

on_stop

Handle the platform's stop event (no-op by default).

on_restart

Handle the platform's restart event (no-op by default).

on_save_instance_state

Handle the platform's save-state request (no-op by default).

on_restore_instance_state

Handle the platform's restore-state event (no-op by default).

on_destroy

Tear down: unmount (running effect cleanups), release native views.

on_back_pressed

Offer the system back action to use_back_handler subscribers.

set_args

Record launch arguments (a dict or a JSON string).

set_focused

Update is_focused and notify focus listeners when the value changes.

set_viewport_size

Forward a viewport-size change (in points) to the reconciler.

request_render

Request a render pass (queued if one is in progress).

flush_scheduled_render

Run a render deferred by _schedule_render_async (platform UI turn).

show_redbox

Mount the dev error overlay over this screen (from any thread).

clear_redbox

Dismiss the dev error overlay, reattaching the app's root view unless reattach is False.

enable_hot_reload

Start polling manifest_path for reloads (see hot_reload_tick) and switch on dev mode.

hot_reload_tick

Poll the reload manifest; returns whether a reload was applied.

reload

Reload modules and refresh the tree (Fast Refresh, else full remount).

initial_navigation_state

initial_navigation_state() -> Optional[Dict[str, Any]]

Return the serialized navigation state from args["pn_nav"], or None for the first screen.

push_screen

push_screen(
    state: Dict[str, Any], options: Dict[str, Any]
) -> None

Push a native screen running the same root component, seeded with state.

pop_screens

pop_screens(count: int) -> None

Pop count native screens (at least one).

replace_screen

replace_screen(
    state: Dict[str, Any], options: Dict[str, Any]
) -> None

Replace the current native screen with one seeded with state.

reset_screens

reset_screens(
    state: Dict[str, Any], options: Dict[str, Any]
) -> None

Rebuild the native stack for state.

The root native screen stays; every route above the first gets its own native screen carrying the history up to it, so the back button walks the new stack.

set_screen_options

set_screen_options(options: Dict[str, Any]) -> None

Apply header options (title and friends) to the native chrome.

add_focus_listener

add_focus_listener(
    callback: Callable[[bool], None],
) -> Callable[[], None]

Subscribe to focus changes (on_resume / on_pause); returns an unsubscribe callable.

on_create

on_create() -> None

Mount the root component (idempotent across native view recreation).

Android destroys and recreates a fragment's view when the user pops back to it and calls on_create again; the Python host persists, so an already-mounted tree is simply re-attached.

on_start

on_start() -> None

Handle the platform's start event (no-op by default).

on_resume

on_resume() -> None

Mark the screen focused and notify focus listeners.

on_layout

on_layout() -> None

Handle a native layout pass (no-op by default; platforms sync the viewport here).

on_pause

on_pause() -> None

Mark the screen unfocused and notify focus listeners.

on_stop

on_stop() -> None

Handle the platform's stop event (no-op by default).

on_restart

on_restart() -> None

Handle the platform's restart event (no-op by default).

on_save_instance_state

on_save_instance_state() -> None

Handle the platform's save-state request (no-op by default).

on_restore_instance_state

on_restore_instance_state() -> None

Handle the platform's restore-state event (no-op by default).

on_destroy

on_destroy() -> None

Tear down: unmount (running effect cleanups), release native views.

on_back_pressed

on_back_pressed() -> bool

Offer the system back action to use_back_handler subscribers.

Returns True when a handler consumed the event, in which case the platform must not pop the screen.

set_args

set_args(args: Any) -> None

Record launch arguments (a dict or a JSON string).

set_focused

set_focused(focused: bool) -> None

Update is_focused and notify focus listeners when the value changes.

set_viewport_size

set_viewport_size(width: float, height: float) -> None

Forward a viewport-size change (in points) to the reconciler.

request_render

request_render() -> None

Request a render pass (queued if one is in progress).

flush_scheduled_render

flush_scheduled_render() -> None

Run a render deferred by _schedule_render_async (platform UI turn).

show_redbox

show_redbox(
    exc: BaseException, phase: str = "render"
) -> None

Mount the dev error overlay over this screen (from any thread).

clear_redbox

clear_redbox(reattach: bool = True) -> None

Dismiss the dev error overlay, reattaching the app's root view unless reattach is False.

enable_hot_reload

enable_hot_reload(
    manifest_path: str, source_root: Optional[str] = None
) -> None

Start polling manifest_path for reloads (see hot_reload_tick) and switch on dev mode.

source_root is accepted for the native templates, which pass the dev directory alongside the manifest; the reloader derives module paths from the manifest itself, so it is currently unused.

hot_reload_tick

hot_reload_tick() -> bool

Poll the reload manifest; returns whether a reload was applied.

reload

reload(
    changed_modules: Optional[Sequence[str]] = None,
) -> None

Reload modules and refresh the tree (Fast Refresh, else full remount).

debug_enabled

debug_enabled() -> bool

Return whether the PYTHONNATIVE_DEBUG environment variable turns on host diagnostics.

log_pn

log_pn(msg: str) -> None

Emit optional diagnostics when PYTHONNATIVE_DEBUG is enabled.

import_component

import_component(component_path: str) -> Any

Import a root component by module path or dotted attribute path.

"app.main" imports the module and returns its App attribute; "app.main.RootScreen" returns the named attribute. Errors raised inside a resolvable module (a missing third-party dependency, a syntax error) propagate unchanged so the real cause stays visible.

Raises:

Type Description
ImportError

When neither form resolves.

flush_hosts

flush_hosts(hosts: Sequence[ScreenHost]) -> None

Run deferred renders for hosts (platform UI-thread drains call this).

Platform hosts

Android screen host: a fragment inside the template's NavHostFragment.

Classes:

Name Description
AndroidScreenHost

Host owned by ScreenFragment.kt; native_instance is the activity.

AndroidScreenHost

AndroidScreenHost(
    native_instance: Any,
    component_path: str,
    component: Any,
)

Bases: ScreenHost

Host owned by ScreenFragment.kt; native_instance is the activity.

Methods:

Name Description
on_create

Publish the system color scheme from the activity, then mount the root component.

on_resume

Refresh the system color scheme, then mark the screen focused.

on_activity_result

Forward Activity.onActivityResult to the native-module dispatcher.

on_request_permissions_result

Forward Activity.onRequestPermissionsResult to the native-module dispatcher.

on_create

on_create() -> None

Publish the system color scheme from the activity, then mount the root component.

on_resume

on_resume() -> None

Refresh the system color scheme, then mark the screen focused.

on_activity_result

on_activity_result(
    request_code: int, result_code: int, data: Any
) -> None

Forward Activity.onActivityResult to the native-module dispatcher.

on_request_permissions_result

on_request_permissions_result(
    request_code: int, permissions: Any, grant_results: Any
) -> None

Forward Activity.onRequestPermissionsResult to the native-module dispatcher.

iOS screen host: one UIViewController per screen, driven by ViewController.swift.

Classes:

Name Description
IOSScreenHost

Host owned by a ViewController; pushes onto its UINavigationController.

IOSScreenHost

IOSScreenHost(
    native_instance: Any,
    component_path: str,
    component: Any,
)

Bases: ScreenHost

Host owned by a ViewController; pushes onto its UINavigationController.

Methods:

Name Description
on_create

Publish the system color scheme, then mount the root component.

on_layout

Sync the root view's frame and viewport size after viewDidLayoutSubviews.

on_resume

Mark the screen focused and refresh the color scheme, root frame, and viewport size.

on_destroy

Drop this host from the view-controller registry, then tear down the tree.

on_create

on_create() -> None

Publish the system color scheme, then mount the root component.

on_layout

on_layout() -> None

Sync the root view's frame and viewport size after viewDidLayoutSubviews.

on_resume

on_resume() -> None

Mark the screen focused and refresh the color scheme, root frame, and viewport size.

on_destroy

on_destroy() -> None

Drop this host from the view-controller registry, then tear down the tree.

Desktop preview host (Tkinter), driven by pn preview.

Placement of the root widget and the screen stack are delegated to the DesktopApp controller in pythonnative.preview (passed as native_instance). The controller runs the Tk event loop on the main thread and polls drain_desktop_scheduled_renders so renders requested from the asyncio worker thread are applied on the main thread.

Classes:

Name Description
DesktopScreenHost

Host for one page of the desktop preview's screen stack.

DesktopScreenHost

DesktopScreenHost(
    native_instance: Any = None,
    component_path: str = "",
    component: Any = None,
)

Bases: ScreenHost

Host for one page of the desktop preview's screen stack.

Next steps