2011-12-30

Ultimate Swing, Teil 11

In meinem vergangenen Post habe Sie mit ziemlich viel Theorie versorgt. Diesmal werden wir uns ansehen, wie das ganze in Notes and Tasks realisiert wird. Zunächst die Schleife, die beim Löschen von Kategorien durchlaufen wird:

        String cmd = e.getActionCommand();
        if (CategoriesView.ACTION_DELETE.equals(cmd)) {
          Category[] categories = CategoriesModel
              .getTypeSafeCategories(categoriesView
                  .getSelectedValues());
          categoriesView.clearSelection();
          for (Category c : categories) {
            new DeleteCategoryWorker(c, categoriesModel,
                categoryDelegate).execute();
          }

Das Quelltextfragment ist länger, weil ich diesmal auch den Kontext dargestellt habe. Die eigentliche Schleife besteht nur aus dem Instantiieren von Objekten des Typs DeleteCategoryWorker und dem Aufruf dessen Methode execute(). Wie sieht die Implementierung der Klasse aus?

public class DeleteCategoryWorker extends SwingWorker<Boolean, Void> {

  private final Category c;
  private final CategoriesModel m;
  private final CategoryDelegate d;

  public DeleteCategoryWorker(Category c, CategoriesModel m,
      CategoryDelegate d) {
    this.c = c;
    this.m = m;
    this.d = d;
  }

  @Override
  protected Boolean doInBackground() throws Exception {
    boolean result = false;
    if (c.getTasks() == 0) {
      result = d.delete(c);
    }
    return new Boolean(result);
  }

  @Override
  protected void done() {
    Boolean result = Boolean.FALSE;
    try {
      result = get();
    } catch (InterruptedException e) {
      handleException(e);
    } catch (ExecutionException e) {
      handleException(e.getCause());
    } finally {
      if (Boolean.TRUE.equals(result)) {
        m.removeCategory(c);
      }
    }
  }

  private void handleException(Throwable t) {
    Application.showErrorMessage(t.getLocalizedMessage());
    t.printStackTrace();
  }
}

Sie erinnern sich, dass das Löschen von Kategorien aus zwei Teilen besteht, von denen der eine Aktion Bedienelemente manipuliert und deshalb auf dem EDT ausgeführt werden muss. Natürlich kommt in so einem Fall nur ein SwingWorker in Frage. Deshalb leitet DeleteCategoryWorker davon ab und überschreibt bzw. implementiert die beiden Methoden doInBackground() und done(). Erstere ruft den Service zum Löschen von Kategorien auf. Letztere löscht die korrespondierende Zeile in der Listbox – aber nur, wenn das physikalische Löschen erfolgreich war und überhaupt durchgeführt wurde. Dies geschieht nämlich nicht, wenn eine Kategorie noch in Aufgaben verwendet wird.

Wie Sie sehen, können wir auf sehr elegante Weise parallel auszuführende Tätigkeiten in passende Threads auslagern. Was aber passiert mit den im vorangehenden Post angesprochenen Mehrfachausgaben von Fehlermeldungen? Mein Worker delegiert das Problem, indem er die Methode showErrorMessage() meiner Klasse Application aufruft. Deren aktuelle Implementierung ist sehr einfach gehalten:

  public static void showErrorMessage(String message) {
    JOptionPane.showMessageDialog(INSTANCE, message,
        getString("string.title"), JOptionPane.ERROR_MESSAGE);
  }

Sie kann meiner Forderung, mehrere Fehlermeldungen zu sammeln, nicht nachkommen. Wir werden die Methode also entsprechend erweitern. Allerdings hat das noch etwas Zeit. Wie geht es nun weiter? In einem Folgeposting werde ich Ihnen einen weiteren Worker vorstellen. Er wird die Grundlage für einige wenige Refactoring-Maßnahmen sein. …spannend? Dann bleiben Sie dran…

PS: Mich würde interessieren, wie Ihnen das Programm bisher gefällt. Es wäre schön, wenn Sie aus den aktuellen Quellen eine Version bauen und ausprobieren würden. Tipp: machen Sie doch einmal einen Doppelklick auf eine Aufgabe…

Quelltexte zu TKNotesAndTasks vom 30.12.2011

No comments:

Post a Comment