1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//! The application of the system: where the framework is set up.
//!
//! The reference is a generic class an application derives its application
//! class from, with two overridable members that make the application
//! builder. Here the application class is a class of the Java layer
//! (`FerroApplication`), which loads the library of the application, and
//! the builder is the function the application gave
//! [`android_application!`](crate::android_application).
use crate::application_lifetime::ApplicationLifetime;
use crate::interop::java::JavaObject;
use ferroui_controls::AppBuilder;
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::OnceLock;
static APPLICATION: OnceLock<JavaObject> = OnceLock::new();
static BUILD: OnceLock<fn() -> AppBuilder> = OnceLock::new();
ferroui_base::ferro_thread_local! {
static LIFETIME: RefCell<Option<Rc<ApplicationLifetime>>> = const { RefCell::new(None) };
}
/// The application of the system.
pub struct FerroAndroidApplication;
impl FerroAndroidApplication {
/// Keeps the function that makes the application builder: what an
/// application overrides `CreateAppBuilder` and `CustomizeAppBuilder`
/// for in the reference.
pub(crate) fn set_builder(build: fn() -> AppBuilder) {
let _ = BUILD.set(build);
}
/// The application object of the system, which is its application
/// context (`Application.Context`).
///
/// # Panics
/// Panics before the application was created.
pub fn context() -> JavaObject {
match APPLICATION.get() {
Some(application) => application.clone(),
None => panic!("The application of the system was not created yet."),
}
}
/// The application context; `None` before the application was created.
pub fn try_context() -> Option<JavaObject> {
APPLICATION.get().cloned()
}
/// The lifetime of the application; `None` before it was created.
pub fn lifetime() -> Option<Rc<ApplicationLifetime>> {
LIFETIME.with(|lifetime| lifetime.borrow().clone())
}
/// Sets the lifetime of the application (`IAndroidApplication.Lifetime`
/// of the reference, set once the application is created).
pub(crate) fn set_lifetime(value: Option<Rc<ApplicationLifetime>>) {
LIFETIME.with(|lifetime| *lifetime.borrow_mut() = value);
}
/// `onCreate` of the application class.
pub(crate) fn on_create(application: JavaObject) {
let _ = APPLICATION.set(application);
Self::initialize_app_lifetime();
}
fn initialize_app_lifetime() {
let Some(build) = BUILD.get() else {
panic!("The library has no application: write `ferroui_android::android_application!(build)`.");
};
let builder = build();
let lifetime = ApplicationLifetime::new();
Self::set_lifetime(Some(lifetime.clone()));
builder.setup_with_lifetime(lifetime);
}
}