2 Stimmen

JTable + TableModel Cache-Abrufereignis für Lazy-Instantiierung?

Szenario:

Sie verwenden eine JTable mit einem benutzerdefinierten TableModel, um den Inhalt einer Sammlung anzuzeigen, die sich in einer Datenbank oder im Netzwerk oder wo auch immer befindet.

Der brute Weg, um dies zu erreichen, besteht darin, die gesamte Sammlung auf einmal zu laden. Angenommen, das ist aufgrund der benötigten Ressourcen nicht praktikabel.

Der einfache Weg, dieses Problem zu umgehen, besteht darin, Zeilen bedarfsweise abzurufen, eine Zeile nach der anderen, wenn die JTable jede Zeile rendert, und TableModel.getValueAt() aufruft; bei Bedarf zwischenspeichern. Dies führt allerdings zu vielen Zugriffen auf die Datenbank.

Gibt es einen Weg, um auf Scroll/Viewport-Ereignisse für eine JTable zu hören, um herauszufinden, welche Zeilen sie anzeigt, bevor sie jede Zelle rendert? Wenn ja, möchte ich eingreifen und mein benutzerdefiniertes TableModel dazu veranlassen, jeweils eine Seite im Voraus zu prefetchen.

Bearbeitung: nur um es klarzustellen, es geht darum, den Inhalt einer Gruppe von sichtbaren Tabellenzeilen in einem Batch abzurufen, anstatt den Inhalt jeder Zeile einzeln abzurufen.

3voto

RubenLaguna Punkte 17855

Schau dir den http://www.javaworld.com/javaworld/javatips/jw-javatip137.html Artikel an. In diesem Artikel gibt es ein benutzerdefiniertes TableModel, das in der Lage ist, "Chunks" von Zeilen aus der Datenbank abzurufen

Ein anderer Lösungsansatz für das Szenario, auch wenn es nicht genau das ist, wonach du suchst, wäre das Lazy-Loading jeder Zeile anstelle von Prefetch. Siehe meinen eigenen Beitrag (Suche bei Google nach "JTable bound to a database with lazy loading"), wie man das macht. Die Idee ist, dass wenn das TableModel nach einer Zeile gefragt wird, die nicht zwischengespeichert/geladen ist, für jede Spalte einen "Warten...Abrufen" String zurückgibt (unter der Annahme, dass alle Spalten Strings sind). und gleichzeitig einen Task in einem anderen Thread plant (unter Verwendung eines ExecutorService). Dann wird der Task die Daten aus der Datenbank abrufen und das Datenmodell aktualisieren. In meinem Beitrag habe ich tatsächlich Beans-Bindungen verwendet, also habe ich anstelle eines benutzerdefinierten TableModels eine benutzerdefinierte Liste verwendet. Aber ich bin sicher, dass du die Idee extrapolieren kannst.

2voto

Houtman Punkte 2739

Im Grunde genommen ist das genau das, was JTable ermöglicht. Nach meinem Kenntnisstand wenn die Methode getRowCount() genau widerspiegelt, wie viele Datensätze es gibt, dann werden nur die sichtbaren Teile abgefragt, wenn die Zellen gemalt werden. Ich denke nicht, dass ein Prefetching durch Zuhören am Viewport schneller wäre.

Sie könnten auf alle getValue-Anfragen warten. Die abfragen, "null" zurückgeben oder den bereits zwischengespeicherten Wert zurückgeben. Dann, nachdem eine getValue-Anfrage nicht innerhalb von etwa 20 ms erfolgt ist, die tatsächliche Anfrage für alle aufgezeichneten Zellen durchführen. und rowUpdated-Ereignisse im Modell auslösen, damit JTable erneut neu gezeichnet wird.

**[Bearbeiten]**Sie könnten eine Liste der zuletzt abgefragten Datensätze im Modell führen. Ihre Liste muss nicht länger sein als die Anzahl der auf dem Bildschirm sichtbaren Zeilen. Nachdem getValue() seit einigen ms nicht abgefragt wurde, könnten Sie diese asynchrone Bulk-Anfrage an das Backend durchführen

Der einzige Haken hier ist der Sortier-/Filteralgorithmus. Wenn Sie den Viewport abfragen und die Daten davon abhängig machen, besteht ein 1:1-Verhältnis zwischen Ihren Daten und der Ansicht. Etwas, das JTable selbst nicht hat. Aber ich denke, daran führt kein Weg vorbei. Ich würde den IDE-Debugger aktivieren, um den Sun-Code zu durchsuchen. und dann sehen, wie deren Rendering-Implementierung herausfindet, welche Zeilen neu gezeichnet werden müssen. Ich weiß es nicht auswendig.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X