2012-01-01

Ultimate Swing, Teil 12

Ich hoffe, Sie sind gut in das Jahr 2012 gestartet und haben weiterhin Lust auf Swing. Wie an anderer Stelle bereits gesagt wird es natürlich auch weiterhin andere Themen, zum Beispiel rund um Android und Mobile Computing geben.

Das Speichern von (neu eingegebenen) Kategorien ist bisher recht schlampig implementiert:

            // FIXME: refactor code to SwingWorker
            Category cat = DTOFactory.createCategory(text);
            if (categoriesModel.addCategory(cat)) {
              if (categoryDelegate.save(cat)) {
                break;
              }
            }
            Application.showErrorMessage(MessageFormat.format(
                Application
                    .getString("string.error_new_category"),
                text));

Analog zum Löschen von Kategorien lässt sich dies sehr schön in einen Worker auslagern.

            Category c = DTOFactory.createCategory(text);
            new SaveCategoryWorker(c, categoriesModel,
                categoryDelegate).execute();

Ich finde, das sieht wesentlich aufgeräumter aus. Hier die Implementierung des Workers:

public class SaveCategoryWorker extends SwingWorker<Boolean, Void> {

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

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

  @Override
  protected Boolean doInBackground() throws Exception {
    boolean result = d.save(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.addCategory(c);
      }
    }
  }

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

Wenn Sie dies mit dem Worker aus dem vorangehenden Post vergleichen, stellen Sie viele Gemeinsamkeiten fest. Der Konstruktor und die Methode handleException() sind identisch. Es liegt nahe, beides in eine abstrakte Elternklasse auszulagern.

public abstract class AbstractCategoryWorker extends SwingWorker<Boolean, Void> {

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

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

  public abstract void doneIfTrue();

  public abstract String getStringForErrorLine1();

  @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)) {
        doneIfTrue();
      }
    }
  }

  private void handleException(Throwable t) {
    String msg = t.getLocalizedMessage();
    if ((msg == null) || (msg.length() < 1)) {
      msg = t.getClass().getName();
    }
    Application.showErrorMessage(MessageFormat.format("{0}\n{1}",
        getStringForErrorLine1(), msg));
    t.printStackTrace();
  }
}

Die Methode handleException() gibt den Klassennamen der Ausnahme aus, wenn getLocalizedMessage() einen Leerstring oder null liefert. Dies war in früheren Versionen meiner Methode noch nicht so (robust) implementiert. Außerdem ist die Fehlermeldung nun zweizeilig. Die erste Zeile wird durch Aufruf der Methode getStringForErrorLine1() ermittelt. Zum Abschluss die deutlich abgespeckte Fassung der Klasse SaveCategoryWorker:

public class SaveCategoryWorker extends AbstractCategoryWorker {

  public SaveCategoryWorker(Category c, CategoriesModel m, CategoryDelegate d) {
    super(c, m, d);
  }

  @Override
  protected Boolean doInBackground() throws Exception {
    boolean result = d.save(c);
    return new Boolean(result);
  }

  @Override
  public void doneIfTrue() {
    m.addCategory(c);
  }

  @Override
  public String getStringForErrorLine1() {
    return MessageFormat.format(
        Application.getString("string.error_new_category"),
        c.getDescr());
  }
}

No comments:

Post a Comment