JavaFx 控制器初始化顺序 - 多次调用数据库
JavaFx Controller Initialization Order - Database Called Multiple times
我有一个扩展应用程序的标准 JavaFX 应用程序。我显示的第一页是一个仪表板,带有用于打开其他应用程序的按钮。没关系,第一个应用程序是一个名为 AdminController 的管理页面,它允许用户对模型对象进行 CRUD 操作——用户、联系人、产品,每个实体都是管理视图上的一个选项卡——所以在我的主要管理 FXML 中(使用 SceneBuilder ) 我使用 fx:include 用户选项卡、联系人选项卡和产品选项卡包括其他 fxml 页面。同样,这些包含都在一个 Admin.fxml 中,有自己的控制器。
<Tab fx:id="contactsTab" onSelectionChanged="#goToContacts" text="Contact">
<content>
<fx:include source="/fxml/manager_contacts_tab.fxml" fx:id="contact" />
</content
<Tab/>
我的想法是加载每个页面需要的资源,users/contacts/products 在 AdminController 中,这样我使用的每个 fx:include 都可以使用相同的对象。由于某些选项卡需要所有这些资源,例如用户来管理关联,而其他选项卡(例如产品)只需要一个产品列表。我的主控制器看起来像这样
我
public class AdminController {
@FXML
UserController userController;
@FXML
ProductController productController;
@FXML
ContactController contactController;
@FXML
public void initialize
// at this point userController already ran, and called DB so it calls it again here
if (users == null) {
this.users = FXCollections.observableArrayList(userDao.getAllWithProductsAndContacts());
}
if (products == null) {
this.products = FXCollections.observableArrayList(productDao.getAll());
}
if (contacts == null) {
this.contacts = FXCollections.observableArrayList(contactDao.getAll());
}
contactController.setContacts(contact);
// set other resources, like products
}
从逻辑上讲,我认为 AdminController 的初始化方法将首先获得 运行,这将允许我在子控制器中设置我需要的任何对象,因为我可以访问它们,但是发生了什么是子控制器首先获得 运行 吗?使用 ContactController
public class ContactController {
@FXML
public void initialize() {
if (contacts == null) {
this.contacts = FXCollections.observableArrayList(contactDao.getAll());
}
}
所以我的应用程序按照它们包含在 admin.fxml userController、contactController、最后是 productController
中的顺序初始化方法 运行
我认为我的问题归结为如何在子控制器之间共享对象,以便在单击具有与前一个资源列表相同的资源列表的新选项卡时,不会启动新的数据库调用 - 在我的示例发生在我加载用户页面时,它需要联系人列表和产品列表,但 ContactController 和 ProductController 需要这些相同的列表,因此不需要进行另一个数据库调用。
在你的情况下,如果你一次加载 "all" 联系人,我可能会在你初始化单个控制器之前调用数据库。
package main;
import javafx.application.Application;
import javafx.stage.Stage;
public class Main extends Application {
public void start(Stage window) throws Exception {
// Database call goes here!
DatabaseManager.initialize();
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
// Whatever window initialization stuff you need to do
window.show();
}
public static void main(String[] args) {
launch(args);
}
}
现在为您的 DatabaseManager class
package sample;
public class DatabaseManager {
public static void initialize() {
// Query the database for your information.
// Little pseudo code here
Data.setUsers(Database.userQuery);
Data.setContacts(Database.contactQuery);
Data.setProducts(Database.productQuery);
}
}
现在数据class
package sample;
public class Data {
public static ArrayList<User> getUsers() {
return users;
}
public static void setUsers(ArrayList<User> users) {
this.users = users;
}
public static ArrayList<Contact> getContacts() {
return contacts;
}
public static void setContacts(ArrayList<Contact> contacts) {
this.contacts = contacts;
}
public static ArrayList<Product> getProducts() {
return products;
}
public static void setProducts(ArrayList<Product> products) {
this.products = products;
}
private static ArrayList<User> users = new ArrayList<User>();
private static ArrayList<Contact> contacts = new ArrayList<Contact>();
private static ArrayList<Product> products = new ArrayList<Product>();
}
现在你的控制器只需要调用
this.contacts = FXCollections.observableArrayList(Data.getContacts());
这将使您的联系人数组列表准备就绪。
另请注意,这就是所谓的"loading it into memory"。换句话说,您将所有这些信息存储在计算机的内存中并从那里访问它。这不适用于巨大的数据库,因为您的计算机没有大脑 space。无论如何,希望这对您有所帮助。
我有一个扩展应用程序的标准 JavaFX 应用程序。我显示的第一页是一个仪表板,带有用于打开其他应用程序的按钮。没关系,第一个应用程序是一个名为 AdminController 的管理页面,它允许用户对模型对象进行 CRUD 操作——用户、联系人、产品,每个实体都是管理视图上的一个选项卡——所以在我的主要管理 FXML 中(使用 SceneBuilder ) 我使用 fx:include 用户选项卡、联系人选项卡和产品选项卡包括其他 fxml 页面。同样,这些包含都在一个 Admin.fxml 中,有自己的控制器。
<Tab fx:id="contactsTab" onSelectionChanged="#goToContacts" text="Contact">
<content>
<fx:include source="/fxml/manager_contacts_tab.fxml" fx:id="contact" />
</content
<Tab/>
我的想法是加载每个页面需要的资源,users/contacts/products 在 AdminController 中,这样我使用的每个 fx:include 都可以使用相同的对象。由于某些选项卡需要所有这些资源,例如用户来管理关联,而其他选项卡(例如产品)只需要一个产品列表。我的主控制器看起来像这样 我
public class AdminController {
@FXML
UserController userController;
@FXML
ProductController productController;
@FXML
ContactController contactController;
@FXML
public void initialize
// at this point userController already ran, and called DB so it calls it again here
if (users == null) {
this.users = FXCollections.observableArrayList(userDao.getAllWithProductsAndContacts());
}
if (products == null) {
this.products = FXCollections.observableArrayList(productDao.getAll());
}
if (contacts == null) {
this.contacts = FXCollections.observableArrayList(contactDao.getAll());
}
contactController.setContacts(contact);
// set other resources, like products
}
从逻辑上讲,我认为 AdminController 的初始化方法将首先获得 运行,这将允许我在子控制器中设置我需要的任何对象,因为我可以访问它们,但是发生了什么是子控制器首先获得 运行 吗?使用 ContactController
public class ContactController {
@FXML
public void initialize() {
if (contacts == null) {
this.contacts = FXCollections.observableArrayList(contactDao.getAll());
}
}
所以我的应用程序按照它们包含在 admin.fxml userController、contactController、最后是 productController
中的顺序初始化方法 运行我认为我的问题归结为如何在子控制器之间共享对象,以便在单击具有与前一个资源列表相同的资源列表的新选项卡时,不会启动新的数据库调用 - 在我的示例发生在我加载用户页面时,它需要联系人列表和产品列表,但 ContactController 和 ProductController 需要这些相同的列表,因此不需要进行另一个数据库调用。
在你的情况下,如果你一次加载 "all" 联系人,我可能会在你初始化单个控制器之前调用数据库。
package main;
import javafx.application.Application;
import javafx.stage.Stage;
public class Main extends Application {
public void start(Stage window) throws Exception {
// Database call goes here!
DatabaseManager.initialize();
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
// Whatever window initialization stuff you need to do
window.show();
}
public static void main(String[] args) {
launch(args);
}
}
现在为您的 DatabaseManager class
package sample;
public class DatabaseManager {
public static void initialize() {
// Query the database for your information.
// Little pseudo code here
Data.setUsers(Database.userQuery);
Data.setContacts(Database.contactQuery);
Data.setProducts(Database.productQuery);
}
}
现在数据class
package sample;
public class Data {
public static ArrayList<User> getUsers() {
return users;
}
public static void setUsers(ArrayList<User> users) {
this.users = users;
}
public static ArrayList<Contact> getContacts() {
return contacts;
}
public static void setContacts(ArrayList<Contact> contacts) {
this.contacts = contacts;
}
public static ArrayList<Product> getProducts() {
return products;
}
public static void setProducts(ArrayList<Product> products) {
this.products = products;
}
private static ArrayList<User> users = new ArrayList<User>();
private static ArrayList<Contact> contacts = new ArrayList<Contact>();
private static ArrayList<Product> products = new ArrayList<Product>();
}
现在你的控制器只需要调用
this.contacts = FXCollections.observableArrayList(Data.getContacts());
这将使您的联系人数组列表准备就绪。
另请注意,这就是所谓的"loading it into memory"。换句话说,您将所有这些信息存储在计算机的内存中并从那里访问它。这不适用于巨大的数据库,因为您的计算机没有大脑 space。无论如何,希望这对您有所帮助。