Dynamisches Laden in Rich-UI

Anstatt alle Rich-UI-Handler in nur einer HTML-Datei zu implementieren, können Sie das Herunterladen des Rich-UI-Handler-Codes während der Ausführung steuern. Bei großen Anwendungen hat dies erhebliche Vorteile für die Skalierbarkeit und die Leistung.

Jeder dynamische Ladevorgang erfolgt asynchron. Sie codieren Listenerfunktionen, um zu reagieren, wenn der Ladevorgang abgeschlossen wird, und der Benutzer kann seine Interaktion mit der Webseite fortsetzen, bis der Ladevorgang abgeschlossen ist.

Beachten Sie als Hintergrundinformation, dass ein Handler auf einen anderen Handler durch zwei Methoden verweisen kann:
Wenn Sie sicherstellen wollen, dass ein Handler vom Anwendungsserver nur während der Ausführung geladen wird, gehen Sie wie folgt vor:

Wenn Sie eine Typenreferenz angeben und den EGL-Implementierungsdeskriptor nicht für das dynamische Laden konfigurieren, hat die Typenreferenz zur Folge, das der referenzierte Handler in den sofort heruntergeladenen Code eingeschlossen wird.

Wie in einem späteren Codebeispiel gezeigt wird, ist eine Typenreferenz erforderlich, wenn Ihr Code direkt auf Felder oder Funktionen im dynamisch geladenen Handler zugreift. Eine Typenreferenz ist jedoch nicht erforderlich, wenn Ihr Code nur auf die Widgetfeldgruppe zugreift, die der Eigenschaft initialUI des dynamisch geladenen Handlers zugeordnet ist.

Dynamische Ladevorgänge werden während der Ausführung durch einen für EGL dedizierten Service mit dem Namen "ModuleLoaderService" ausgeführt. Ändern Sie diesen Service nicht, da er mit internen Details arbeitet, die in zukünftigen Versionen des Produkts geändert werden könnten.

Weitere Details finden Sie in den folgenden Abschnitten:

Ein Beispiel für die Verwendung des dynamischen Loaders finden Sie in “EGL-Dojo-Widgets” und dort insbesondere in der Datei GalleryDynamicLoading.egl.

DynamicLoader-Funktionen

Die Bibliothek DynamicLoader enthält die folgenden Funktionen zusammen mit den Listenerfunktionen (später beschrieben), die auf Ihren Aufruf antworten:
  • loadHandler (handlerName String in)

    Diese Funktion lädt einen Handler.

    handlerName
    Der vollständig qualifizierte Name des Handlers, der dynamisch geladen werden soll, wie in dem Beispiel, das zuvor gezeigt wurde.
  • loadHandlerNoInstantiation (handlerName String in)

    Diese Funktion lädt die Handlertypdefinition, jedoch keine Handlerinstanz. Sie können diese Funktion verwenden, um eine bessere Laufzeitleistung zu erzielen. Sie könnten zum Beispiel wünschen, dass ein Handlertyp in Ihrer Anwendung verfügbar ist, den Handler selbst jedoch nur erstellen, wenn der Benutzer auf einen Menüpunkt klickt, der den Handler erfordert.

    handlerName
    Der vollständig qualifizierte Name des Handlers, der dynamisch geladen werden soll.
  • unloadHandler (handlerName String in)

    Diese Funktion entlädt einen Handler aus dem Speicher, löscht jedoch nicht die Instanzen dieses Handlers. Sie können keine EGL-Bibliotheken entladen, die verfügbar sind, bis eine Anwendung beendet wird.

    Eine Handlerinstanz kann nicht aus dem Speicher entfernt werden, wenn eine der folgenden Bedingungen zutrifft:
    • Der Handler wird nach Typ in einem anderen Handler referenziert, der nicht aus dem Speicher entfernt wird.
    • Der Handler hat den Infobus subskribiert, wie in “Rich-UI-Infobus” beschrieben.

    In den meisten Fällen wird der Speicher durch den EGL-Laufzeitcode freigegeben. Im folgenden Abschnitt wird jedoch beschrieben, wie eine größere Kontrolle über die Speicherverwaltung realisiert werden kann: “Rich-UI-Speicherverwaltung”.

    handlerName
    Der vollständig qualifizierte Name des Handlers, der entladen werden soll.
  • showDebugView()

    Diese Funktion stellt sicher, dass Details angezeigt werden, die Aufschluss über die Vorgänge im dynamischen Loader geben. Sie können diese Funktion in der onConstruction-Funktion Ihres Haupthandlers angeben.

Feldgruppen für DynamicLoader-Listener

Die Bibliothek DynamicLoader stellt einen Mechanismus bereit, mit dem Sie Listener entsprechend einem Stellvertreterabschnitt ('Delegate') codieren und diese Listener anschließend einer Feldgruppe zuordnen, um auf diese Weise auf Ereignisse während der Ausführung zu antworten. Das folgende Beispiel zeigt eine solche Verwendung:
function start()
   // Handler festlegen für das Ereignis, dass die Seite geladen wurde
   DynamicLoader.loadDoneListeners ::= processLoadDone;

   DynamicLoader.loadHandler("myPkg.Secondary");
end

function processLoadDone (event HandlerLoadedEvent in)
   
   // Die initialUI-Widgets der aktuellen Seite zuordnen.
   // Dieser Schritt erfordert keine Typenreferenz.
   div.children = event.initialUI;

   // Auf eine Funktion im geladenen Handler zugreifen
   theHandler any = event.theHandler;

   // Die Verwendung eines Handlers (oder anderen Containers) vom Typ ANY erfordert
   // eine Typenreferenz, sodass der Code direkt auf ein Feld oder eine Funktion
   // zugreifen kann, das bzw. die in diesem Container enthalten ist.
   if (theHandler isa Secondary)
      p1 Page1 = theHandler as Secondary;
      p1.doTask();
   end
end
Das folgende Beispiel zeigt den Datensatzabschnitt HandlerLoadedEvent, der die Informationen angibt, die aus dem Parameter event für processLoadDone verfügbar sind:
record HandlerLoadedEvent

   // Der Name des Handlers
   name String;

   // Die durch den Rich-UI-Handler definierten Widgets
   initialUI Widget[];

   // Eine Referenz auf den Rich-UI-Handler
   theHandler any;
end
Die folgenden Listener und zugehörigen Stellvertreterabschnitte werden von der Bibliothek DynamicLoader bereitgestellt:
  • DynamicLoader.loadDoneListeners
    Diese Feldgruppe gibt eine Reihe von Listenern an, die nach dem Laden des Handlers aufgerufen werden. Der Stellvertreterabschnitt sieht wie folgt aus:
    delegate
       LoadDoneListener (event HandlerLoadedEvent in)
    end
    event
    Wie zuvor gezeigt. Wenn jedoch ein Listener als Antwort darauf ausgeführt wird, dass Sie die Funktion loadHandlerNoInstantiation aufgerufen haben, empfängt der Parameter initialUI eine leere Feldgruppe und der Parameter theHandler empfängt den Wert 'null'.
  • DynamicLoader.loadFailListeners
    Diese Feldgruppe gibt eine Reihe von Listenern an, die aufgerufen werden, wenn das Laden fehlschlägt. Der Stellvertreterabschnitt sieht wie folgt aus:
    delegate
       LoadFailListener (handlerName string in, msg string in) 
    end
    handlerName
    Der vollständig qualifizierte Name des Handlers, der nicht geladen werden konnte.
    msg
    Eine Fehlernachricht.
    Beispiel:
    function start()
       DynamicLoader.loadFailListeners ::= processLoadFail;
       DynamicLoader.loadHandler("myPkg.Secondary");
    end    
    
    Function processLoadFail (handlerName string in, msg string in)    
       Syslib.writeStdErr(handlerName + “ failed to load. ” + msg);
    end
  • DynamicLoader.loadInfoListeners
    Diese Feldgruppe gibt eine Reihe von Listenern an, die vom dynamischen Loader aufgerufen werden und zum Tracing des Herunter- und Entladeverhaltens während der Ausführung verwendet werden. Die Gruppe wird einmal für jede hochgeladene oder entladene Ressource aufgerufen. Dabei kann eine Ressource eine der folgenden Einheiten sein:
    • Abschnitte:
      • Rich-UI-Handler
      • Basishandler
      • Widgets
      • Bibliotheken, einschließlich Rich-UI-Eigenschaftenbibliotheken
      • Datensätze
    • Andere Ressourcen:
      • JavaScript-Include-Dateien, entweder global definiert oder in einem externen Typ referenziert
      • Eigenschaftendateien, die zu einer Rich-UI-Eigenschaftenbibliothek gehören
      • Servicebindungsdateien, die zu einem EGL-Implementierungsdeskriptor gehören
    Der Stellvertreterabschnitt sieht wie folgt aus:
    delegate
       LoadInfoListener (handlerName string, resourceName string, 
                         code string, msg string)
    end
    handlerName
    Der vollständig qualifizierte Name des Handlers, der an eine Lade- oder Entladefunktion übergeben wurde.
    resourceName
    Der Name einer heruntergeladenen oder entladenen Ressource.
    code
    Einer der folgenden Codes, die jeweils einen Typ von Information angeben:
    • DynamicLoader.INFO_LOAD: Gibt an, dass die Ressource geladen wurde.
    • DynamicLoader.INFO_UNLOAD: Gibt an, dass die Ressource aus dem Speicher entladen wurde.
    • DynamicLoader.INFO_UNLOAD_SKIP: Gibt an, dass die Ressource nicht entladen wurde, zum Beispiel weil die Ressource eine Bibliothek war.
    • DynamicLoader.INFO_DEBUG: Eine generische Nachricht aus dem dynamischen Loader.
    msg
    Eine Nachricht.
    Beispiel:
    function start()
       DynamicLoader.loadInfoListeners ::= processLoadInfo;
       DynamicLoader.loadHandler("myPkg.Secondary");
    end
    
    function processLoadInfo (handlerName string, 
       resourceName string, code string, msg string)
       if (code == DynamicLoader.INFO_UNLOAD)
          Syslib.writeStdErr(resourceName + “ unloaded.”);
       end
    end

Handlerinstanzen

Sie können neue Instanzen eines Handlers erstellen, nachdem der Handler geladen wurde, wie im folgenden Beispiel gezeigt:
function createPage1() returns (Secondary)
   anotherPage1 Secondary = new Secondary{};
   return(anotherPage1);
end  
Versuchen Sie nicht, eine neue Instanz zu erstellen, bevor der Handler geladen wurde. Beispiel:
handler MainHandler type RUIhandler {onConstructionFunction = start }

   // Fehler!
   anotherPage1 Page1 = new Secondary{};   
end

Hinweise für die Verwendung von CSS-Dateien während der Ausführung

Wenn der EGL-Implementierer die HTML-Datei für einen Handler erstellt, enthält die Datei eine Liste aller CSS-Dateien, die in der Rich-UI-Anwendung verwendet werden. CSS-Dateien werden nicht dynamisch geladen.

Die Prioritäten für die CSS-Definitionen haben die folgende Reihenfolge:
  • Auf der höchsten Ebene befinden sich die Definitionen des Handlers der höchsten Ebene.
  • Als Nächstes kommen die Definitionen in den anderen Handlern, die sich in der HTML-Datei befinden.
  • Auf der untersten Ebene befinden sich die Definitionen in den Handlern, die dynamisch geladen werden.

Hinweise für die Verwendung der Vorschauanzeige des Rich-UI-Editors

Wenn Sie einen Handler in der Vorschauanzeige des Rich-UI-Editors ausführen, gelten die folgenden Regeln:
  • Die Workbench erstellt eine HTML-Datei, die alle Ressourcen einschließt, die nach Typ in dem Handler, der bearbeitet wird, referenziert werden, oder die nach Typ in einem Handler referenziert werden, der von einem dieser Handler der zweiten Ebene referenziert wird usw. bis zu einer beliebigen Referenzebene.
  • Die einzigen Handler, die dynamisch geladen werden, sind die Handler, die durch eine Zeichenfolge und nicht durch eine Typenreferenz angegeben werden.
Für die Handler, die dynamisch in der Vorschauanzeige geladen werden, ist Folgendes zu beachten:
  • Die CSS-Dateien und Include-Dateien, die in den dynamisch geladenen Handlern angegeben sind, stehen für Vorschauanzeige nicht zur Verfügung. Sie müssen diese Dateien in dem Handler, der bearbeitet wird, oder in einem Handler, der direkt oder indirekt durch eine Typenreferenz in dem Handler, den Sie bearbeiten, geladen wird, referenzieren.
  • Die müssen JavaScript-Laufzeitdateien verarbeiten, selbst wenn Sie sie ansonsten nicht referenzieren würden. Beispiel: Wenn Handler A keine EGL-Dojo-Widgets verwendet und Handler B nur durch eine Zeichenfolge referenziert, Handler B jedoch EGL-Dojo-Widgets verwendet, müssen Sie die Eigenschaft includeFile von Handler A festlegen, um den Dojo-Laufzeitcode zu referenzieren, wie im folgenden Beispiel gezeigt:
    { includeFile = "config/includeDojo.html" }

Feedback