|
| 1 | +# Architecture |
| 2 | + |
| 3 | +PythonNative maps Python directly to native platform APIs. Conceptually, it is closer to NativeScript's dynamic bindings than to React Native's bridge-and-module approach. |
| 4 | + |
| 5 | +## High-level model |
| 6 | + |
| 7 | +- Direct bindings: call native APIs synchronously from Python. |
| 8 | + - iOS: rubicon-objc exposes Objective-C/Swift classes (e.g., UIViewController, UIButton, WKWebView) and lets you create dynamic Objective-C subclasses and selectors. |
| 9 | + - Android: Chaquopy exposes Java classes (e.g., android.widget.Button, android.webkit.WebView) via the java bridge so you can construct and call methods directly. |
| 10 | +- Shared Python API: components like Page, StackView, Label, Button, and WebView have a small, consistent surface. Platform-specific behavior is chosen at import time using pythonnative.utils.IS_ANDROID. |
| 11 | +- Thin native bootstrap: the host app remains native (Android Activity or iOS UIViewController). It passes a live instance/pointer into Python, and Python drives the UI from there. |
| 12 | + |
| 13 | +## Comparison |
| 14 | + |
| 15 | +- Versus React Native: RN typically exposes capabilities via native modules/TurboModules and a bridge. PythonNative does not require authoring such modules for most APIs; you can access platform classes directly from Python. |
| 16 | +- Versus NativeScript: similar philosophy—dynamic, synchronous access to Obj-C/Java from the scripting runtime. |
| 17 | + |
| 18 | +## iOS flow (Rubicon-ObjC) |
| 19 | + |
| 20 | +- The iOS template (Swift + PythonKit) boots Python and calls your bootstrap(native_instance) with the UIViewController pointer. |
| 21 | +- In Python, Rubicon wraps the pointer; you then interact with UIKit classes directly. |
| 22 | + |
| 23 | +```python |
| 24 | +from rubicon.objc import ObjCClass, ObjCInstance |
| 25 | + |
| 26 | +UIButton = ObjCClass("UIButton") |
| 27 | +vc = ObjCInstance(native_ptr) # passed from Swift template |
| 28 | +button = UIButton.alloc().init() |
| 29 | +# Configure target/action via a dynamic Objective-C subclass (see Button implementation) |
| 30 | +``` |
| 31 | + |
| 32 | +## Android flow (Chaquopy) |
| 33 | + |
| 34 | +- The Android template (Kotlin + Chaquopy) initializes Python in MainActivity and provides the current Activity/Context to Python. |
| 35 | +- Components acquire the Context implicitly and construct real Android views. |
| 36 | + |
| 37 | +```python |
| 38 | +from java import jclass |
| 39 | +from pythonnative.utils import get_android_context |
| 40 | + |
| 41 | +WebViewClass = jclass("android.webkit.WebView") |
| 42 | +context = get_android_context() |
| 43 | +webview = WebViewClass(context) |
| 44 | +webview.loadUrl("https://example.com") |
| 45 | +``` |
| 46 | + |
| 47 | +## Key implications |
| 48 | + |
| 49 | +- Synchronous native calls: no JS bridge; Python calls are direct. |
| 50 | +- Lifecycle rules remain native: Activities/ViewControllers are created by the OS. Python receives and controls them; it does not instantiate Android Activities directly. |
| 51 | +- Small, growing surface: the shared Python API favors clarity and consistency, expanding progressively. |
| 52 | + |
| 53 | +## Related docs |
| 54 | + |
| 55 | +- Guides / Android: guides/android.md |
| 56 | +- Guides / iOS: guides/ios.md |
| 57 | +- Concepts / Components: concepts/components.md |
0 commit comments