Skip to content

Commit c4e2639

Browse files
committed
Update PythonNative Page
1 parent d417237 commit c4e2639

File tree

3 files changed

+76
-67
lines changed
  • apps
    • android_pythonnative_3/app/src/main/python/app
    • pythonnative_demo/app
  • libs/pythonnative/pythonnative

3 files changed

+76
-67
lines changed

apps/android_pythonnative_3/app/src/main/python/app/main_3.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22

33

44
class MainPage(pn.Page):
5-
def __init__(self, context):
6-
super().__init__()
7-
self.context = context
5+
def __init__(self, native_instance):
6+
super().__init__(native_instance)
87

98
def on_create(self):
109
super().on_create()
10+
stack_view = pn.StackView(self.native_instance)
11+
button = pn.Button(self.native_instance, "Button")
12+
label = pn.Label(self.native_instance, "Label")
13+
stack_view.add_view(button)
14+
stack_view.add_view(label)
15+
self.set_root_view(stack_view)
1116

1217
def on_start(self):
1318
super().on_start()

apps/pythonnative_demo/app/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def main():
1717
stack_view.add_view(label)
1818

1919
# Set the layout
20-
page.set_layout(stack_view)
20+
page.set_root_view(stack_view)
2121

2222
# Display the page
2323
page.show()
Lines changed: 67 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,34 @@
1+
"""
2+
Your current approach, which involves creating an Android Activity in Kotlin
3+
and then passing it to Python, is necessary due to the restrictions inherent
4+
in Android's lifecycle. You are correctly following the Android way of managing
5+
Activities. In Android, the system is in control of when and how Activities are
6+
created and destroyed. It is not possible to directly create an instance of an
7+
Activity from Python because that would bypass Android's lifecycle management,
8+
leading to unpredictable results.
9+
10+
Your Button example works because Button is a View, not an Activity. View
11+
instances in Android can be created and managed directly by your code. This is
12+
why you are able to create an instance of Button from Python.
13+
14+
Remember that Activities in Android are not just containers for your UI like a
15+
ViewGroup, they are also the main entry points into your app and are closely
16+
tied to the app's lifecycle. Therefore, Android needs to maintain tight control
17+
over them. Activities aren't something you instantiate whenever you need them;
18+
they are created in response to a specific intent and their lifecycle is
19+
managed by Android.
20+
21+
So, to answer your question: Yes, you need to follow this approach for
22+
Activities in Android. You cannot instantiate an Activity from Python like you
23+
do for Views.
24+
25+
On the other hand, for iOS, you can instantiate a UIViewController directly
26+
from Python. The example code you provided for this is correct.
27+
28+
Just ensure that your PythonNative UI framework is aware of these platform
29+
differences and handles them appropriately.
30+
"""
31+
132
from abc import ABC, abstractmethod
233
from .utils import IS_ANDROID
334
from .view import ViewBase
@@ -11,54 +42,45 @@ class PageBase(ABC):
1142
@abstractmethod
1243
def __init__(self) -> None:
1344
super().__init__()
14-
self.layout = None
15-
16-
@abstractmethod
17-
def add_view(self, view) -> None:
18-
pass
1945

2046
@abstractmethod
21-
def set_layout(self, layout) -> None:
47+
def set_root_view(self, view) -> None:
2248
pass
2349

2450
@abstractmethod
25-
def show(self) -> None:
51+
def on_create(self) -> None:
2652
pass
2753

2854
@abstractmethod
29-
def on_create(self):
55+
def on_start(self) -> None:
3056
pass
3157

3258
@abstractmethod
33-
def on_start(self):
59+
def on_resume(self) -> None:
3460
pass
3561

3662
@abstractmethod
37-
def on_resume(self):
63+
def on_pause(self) -> None:
3864
pass
3965

4066
@abstractmethod
41-
def on_pause(self):
67+
def on_stop(self) -> None:
4268
pass
4369

4470
@abstractmethod
45-
def on_stop(self):
71+
def on_destroy(self) -> None:
4672
pass
4773

4874
@abstractmethod
49-
def on_destroy(self):
75+
def on_restart(self) -> None:
5076
pass
5177

5278
@abstractmethod
53-
def on_restart(self):
79+
def on_save_instance_state(self) -> None:
5480
pass
5581

5682
@abstractmethod
57-
def on_save_instance_state(self):
58-
pass
59-
60-
@abstractmethod
61-
def on_restore_instance_state(self):
83+
def on_restore_instance_state(self) -> None:
6284
pass
6385

6486

@@ -70,49 +92,40 @@ def on_restore_instance_state(self):
7092
from java import jclass
7193

7294
class Page(PageBase, ViewBase):
73-
def __init__(self):
95+
def __init__(self, native_instance) -> None:
7496
super().__init__()
7597
self.native_class = jclass("android.app.Activity")
98+
self.native_instance = native_instance
7699
# self.native_instance = self.native_class()
77100

78-
def add_view(self, view):
79-
if self.layout is None:
80-
raise ValueError("You must set a layout before adding views.")
81-
self.layout.add_view(view)
82-
83-
def set_layout(self, layout):
84-
self.layout = layout
85-
self.native_instance.setContentView(layout.native_instance)
86-
87-
def show(self):
88-
# This method should contain code to start the Activity
89-
pass
101+
def set_root_view(self, view) -> None:
102+
self.native_instance.setContentView(view.native_instance)
90103

91-
def on_create(self):
104+
def on_create(self) -> None:
92105
print("Android on_create() called")
93106

94-
def on_start(self):
107+
def on_start(self) -> None:
95108
print("Android on_start() called")
96109

97-
def on_resume(self):
110+
def on_resume(self) -> None:
98111
print("Android on_resume() called")
99112

100-
def on_pause(self):
113+
def on_pause(self) -> None:
101114
print("Android on_pause() called")
102115

103-
def on_stop(self):
116+
def on_stop(self) -> None:
104117
print("Android on_stop() called")
105118

106-
def on_destroy(self):
119+
def on_destroy(self) -> None:
107120
print("Android on_destroy() called")
108121

109-
def on_restart(self):
122+
def on_restart(self) -> None:
110123
print("Android on_restart() called")
111124

112-
def on_save_instance_state(self):
125+
def on_save_instance_state(self) -> None:
113126
print("Android on_save_instance_state() called")
114127

115-
def on_restore_instance_state(self):
128+
def on_restore_instance_state(self) -> None:
116129
print("Android on_restore_instance_state() called")
117130

118131
else:
@@ -123,47 +136,38 @@ def on_restore_instance_state(self):
123136
from rubicon.objc import ObjCClass
124137

125138
class Page(PageBase, ViewBase):
126-
def __init__(self):
139+
def __init__(self, native_instance) -> None:
127140
super().__init__()
128141
self.native_class = ObjCClass("UIViewController")
142+
self.native_instance = native_instance
129143
# self.native_instance = self.native_class.alloc().init()
130144

131-
def add_view(self, view):
132-
if self.layout is None:
133-
raise ValueError("You must set a layout before adding views.")
134-
self.layout.add_view(view)
135-
136-
def set_layout(self, layout):
137-
self.layout = layout
138-
self.native_instance.view().addSubview_(layout.native_instance)
139-
140-
def show(self):
141-
# This method should contain code to present the ViewController
142-
pass
145+
def set_root_view(self, view) -> None:
146+
self.native_instance.view().addSubview_(view.native_instance)
143147

144-
def on_create(self):
148+
def on_create(self) -> None:
145149
print("iOS on_create() called")
146150

147-
def on_start(self):
151+
def on_start(self) -> None:
148152
print("iOS on_start() called")
149153

150-
def on_resume(self):
154+
def on_resume(self) -> None:
151155
print("iOS on_resume() called")
152156

153-
def on_pause(self):
157+
def on_pause(self) -> None:
154158
print("iOS on_pause() called")
155159

156-
def on_stop(self):
160+
def on_stop(self) -> None:
157161
print("iOS on_stop() called")
158162

159-
def on_destroy(self):
163+
def on_destroy(self) -> None:
160164
print("iOS on_destroy() called")
161165

162-
def on_restart(self):
166+
def on_restart(self) -> None:
163167
print("iOS on_restart() called")
164168

165-
def on_save_instance_state(self):
169+
def on_save_instance_state(self) -> None:
166170
print("iOS on_save_instance_state() called")
167171

168-
def on_restore_instance_state(self):
172+
def on_restore_instance_state(self) -> None:
169173
print("iOS on_restore_instance_state() called")

0 commit comments

Comments
 (0)