JavaFx控制器初始化顺序-多次调用数据库

JavaFx控制器初始化顺序-多次调用数据库,java,javafx,controller,scenebuilder,Java,Javafx,Controller,Scenebuilder,我有一个标准的JavaFX应用程序,它扩展了应用程序。我显示的第一个页面是一个仪表板,上面有打开其他应用程序的按钮。这很好,第一个应用程序是一个名为AdminController的管理页面,它允许用户对模型对象进行CRUD操作-用户、联系人、产品每个实体都是管理视图上的一个选项卡-因此在我的主管理FXML(使用SceneBuilder)中,我使用fx包括其他FXML页面:包括用户选项卡、联系人选项卡和产品选项卡。同样,这些包含都在一个Admin.fxml中,有自己的控制器 <Tab fx:

我有一个标准的JavaFX应用程序,它扩展了应用程序。我显示的第一个页面是一个仪表板,上面有打开其他应用程序的按钮。这很好,第一个应用程序是一个名为AdminController的管理页面,它允许用户对模型对象进行CRUD操作-用户、联系人、产品每个实体都是管理视图上的一个选项卡-因此在我的主管理FXML(使用SceneBuilder)中,我使用fx包括其他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/>
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);
    }

}
从逻辑上讲,我认为AdminController的initialize方法将首先运行,这将允许我在子控制器中设置我需要的任何对象,因为我可以访问它们,但现在发生的是子控制器首先运行,例如使用ContactController

public class ContactController {
    @FXML
    public void initialize() {
        if (contacts == null) {
            this.contacts = FXCollections.observableArrayList(contactDao.getAll());
        }
    }
因此,我的应用程序初始化方法的运行顺序是admin.fxml userController、contactController,最后是productController


我想我的问题可以归结为如何在子控制器之间共享对象,以便在单击与前一个选项卡具有相同资源列表的新选项卡时,新的数据库调用未启动-在我的示例中,当我加载用户页面时会发生这种情况,它需要联系人列表和产品列表,但ContactController和ProductController需要这些相同的列表,因此不需要再进行一次数据库调用。

在您的情况下,如果您加载的是“全部”在初始化单个控制器之前,我可能会立即调用数据库

<Tab fx:id="contactsTab" onSelectionChanged="#goToContacts" text="Contact">
   <content>
     <fx:include source="/fxml/manager_contacts_tab.fxml" fx:id="contact" />
   </content
<Tab/>
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类

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);
    }

}
现在是数据类

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>();

}
这将使您的联系人列表准备就绪


还要注意,这就是所谓的“将其加载到内存中”。换言之,您将所有信息存储在计算机内存中,并从那里访问它。这对于一个庞大的数据库来说是行不通的,因为你的计算机根本没有大脑空间。不管怎样,希望这能有所帮助。

对我来说,你在这里问什么还不是100%清楚。你说的数据库调用是什么意思?通常,您只需查询一个DB(除非您正在修改它),并且只需ms即可完成。否则(如果数据库足够小),您可以在程序启动时将其加载到内存中,而不在控制器中获取它。“数据库”是指一组序列化的文件还是指SQL数据库?我通常使用小型存储来定义一个名为“Data”的类,并在其中存储包含数据库对象(如用户、产品等)的ArrayList。我在程序启动时加载这些数组列表。这样,控制器就可以调用类似Data.getContacts()的东西;抓住所有的联系人。如果我们谈论的是一个巨大的数据库,那么应该运行SQL查询来获取信息。对不起,应该已经澄清了-这是一个SQL数据库,我想我的问题不是首先在哪里调用数据库来获取我正在使用的项的列表-我的第一个想法是在AdminController中执行所有数据库调用来设置ChildController,但是子控制器在AdminController之前初始化,因此此时需要进行调用,并且共享相同数据列表的子控制器彼此不可见,例如Contact/Admin控制器-ContactController需要联系人,但UserController也需要联系人(以显示两者之间的关联)。谢谢!现在我的应用程序已经足够小了,但是计划是它将发展成一个大型应用程序,你对大型应用程序有什么建议吗?理想情况下,我只希望在必要时加载它,但是controller@FXML初始化让我感到困惑,并且没有按照我期望的顺序操作。我的期望where->AdminController-加载视图所需的内容,以便与此控制器相关的视图,即ContactController可以访问AdminControllers-只有ContactController首先初始化。老实说,我从不喜欢控制器的“初始化”方法。这对我来说也有点不稳定。我不确定你的程序是如何运行的,但对我来说,我在所有FX项目中所做的是创建一个“控制器”类,并从该类扩展我的所有其他控制器,我有一个公共start()方法,我在父类中创建了这个方法,每当我加载一个控制器时,我调用start()方法。所有的扩展控制器都会覆盖start()方法。谢谢你,Phillip,我很感谢你的回答-我会再摆弄一下,看看我能想出什么。再摆弄一下,你为什么要麻烦呢,我用你的抽象控制器方式,它解决了我的问题,干杯。