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

时间:2017-07-13 19:15:27

标签: java javafx controller scenebuilder

我有一个扩展Application的标准JavaFX App。我展示的第一页是一个仪表板,其中包含用于打开其他应用程序的按钮。这很好,第一个应用程序是一个名为AdminController的管理页面,允许用户对模型对象进行CRUD操作 - 用户,联系人,产品,每个实体都是管理视图上的选项卡 - 所以在我的主要Admin 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/>

我的想法是在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,finally productController中的顺序运行

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

1 个答案:

答案 0 :(得分:1)

在您的情况下,如果您一次性加载“全部”联系人,我可能会在初始化单个Controller之前调用数据库。

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

}

现在是Data类

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

这将使你的联系人的arraylist准备就绪。

另请注意,这就是所谓的“将其加载到内存中”。另一个词是你将所有信息存储在计算机的内存中并从那里访问它。这对于巨大的数据库不起作用,因为你的计算机不会有大脑空间。无论如何,希望这会有所帮助。