Skip to content
Advertisement

Gluon reusing view and populating prefeably using a protected event hook

In Gluon you register a view factory, Gluon uses this to create a view when needed.

addViewFactory(HOME_VIEW, () -> new LoginView());
addViewFactory(SelectView.class.getSimpleName(), () -> new SelectView());

You then switch a view using:

MobileApplication.getInstance().switchView(SelectView.class.getSimpleName());

If you are on the SelectView and want to go back, you can use this:

MobileApplication.getInstance().switchToPreviousView();

Now to the problem: after going to SelectView, back to the previous, and then to the SelectView again, Gluon decides not to create a new view but reuse the existing one. This is not really a problem, probably even a good thing, it just means the init code needs to be split into a “createView” and “populateView” method. The populateView method is called in the onShowing event. All good.

My issue is with that I cannot seem to override an ‘onShowing()’ method for this, but need to actually register using the setOnShowing method. That seems not only to be a deviation from the standard way of doing things (e.g. like overriding the updateAppBar method), but it also means claiming an event hook for inside usage that really is more intended for outside usage (by external listeners).

Am I doing something wrong?

  • Should Gluon create a new view when revisiting?
  • Or is there an onShowing() method to override?

Advertisement

Answer

Gluon’s Views are cached, for performance reasons. Whenever you add one view, you are providing a supplier, that will be called when the view is required. At this point, the view will be added to a cache, and the next time you need the same view, it will be retrieved from that cache. Only if it is not found, for instance under memory constrains it can be removed, it will be created again from the supplier.

So, as you say, it makes sense having one time only code for the view (your “createView”), that stays the same for the whole lifecycle of that view, and also mutable code that is called every time the view is shown (your “populateView”), but taken from the cache, without calling its constructor.

For projects with a number of views, it is more convenient to use an MVP approach, with FXML and the Gluon Glisten-Afterburner framework.

In this case, the view is created and registered once, and the presenter can be used to define the view via initialize().

If you check any of the samples that use this approach (like the Notes app), you’ll see:

  • Register view (Notes view is an AppView that creates a GluonView that extends from FXMLView):

    public static final AppView NOTES_VIEW = view("Notes", NotesPresenter.class, MaterialDesignIcon.HOME, SHOW_IN_DRAWER, HOME_VIEW, SKIP_VIEW_STACK);
    
  • Create presenter:

    public class NotesPresenter extends GluonPresenter<NotesApp>  {
    
        @FXML private View notes;
    
        public void initialize() {
             // one time only code
             ...
             // code required each time the view is displayed
        }
    
    }
    

Now you can use some of the View’s properties like showingProperty(), onShowingProperty(), onShownProperty() to add listeners that can’t be removed or overriden from outside the view:

public void initialize() {
    notes.showingProperty().addListener((obs, oldValue, newValue) -> {
        if (newValue) {
            // update appBar 
            AppBar appBar = getApp().getAppBar();
            ...
        }
    });
}

The same can be applied to regular Views, of course:

View view = new View() {

    private final Label label;
    {
        label = new Label("some text");

        showingProperty().addListener((obs, ov, nv) -> {
            if (nv) {
                // update view
                label.setText("new text");
            }
        });
        onShownProperty().addListener((obs, ov, nv) -> {
            // add something when view is fully shown
        });
        onHiddenProperty().addListener((obs, ov, nv) -> {
            // remove something when view is hidden
        });
    }

    @Override
    protected void updateAppBar(AppBar appBar) {
        ...
    }

};     
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement