3.16.2. Observable Value Binding

Die Klasse org.jowidgets.util.binding.Bind kann verwendet werden, um zwei Observable Values aneinander zu binden binden. Sie hat die folgenden statischen Methoden:

    public static <VALUE_TYPE> IBinding bind(
        final IObservableValue<VALUE_TYPE> source,
        final IObservableValue<VALUE_TYPE> destination) {...}

    public static <SOURCE_TYPE, DESTINATION_TYPE> IBinding bind(
        final IObservableValue<SOURCE_TYPE> source,
        final IObservableValue<DESTINATION_TYPE> destination,
        final IBindingConverter<SOURCE_TYPE, DESTINATION_TYPE> converter) {...}

Die erste Methode kann verwendet werden, um typgleiche Values aneinander zu binden, die zweite Methode erlaubt das Binden von unterschiedlichen Typen. Die Bindung ist immer bidirektional, das bedeutet, Änderungen auf source ändern die destination und Änderungen auf destination ändern die source. Haben source und destination initial einen unterschiedlichen Wert, nimmt durch das Binden destination den Wert von source an. Beide Methoden liefern eine IBinding Referenz zurück. Diese hat die folgenden Methoden:

    void setBindingState(boolean bind);

    void unbind();

    void bind();
    
    boolean isBound();

    void dispose();
    
    boolean isDisposed();

Die ersten drei Methoden dienen zum Setzen, die vierte zum Auslesen des binding State. Dadurch kann das Binding temporär gelöst und später wieder aktiviert werden. Initial ist der binding State true. Durch den Aufruf von dispose() wird das Binding dauerhaft gelöst, und die internen Referenzen auf source und destination verworfen. Nach einem Aufruf von dispose() kann nur noch die Methode isDisposed() aufgerufen werden. Alle anderen Methodenaufrufe führen dann zu einer IllegalStateException.

Binding Converter

Um Obervable Values unterschiedlichen Typs zu binden, kann ein IBindingConverter verwendet werden. Dieser ist wie folgt definiert:

  1  public interface IBindingConverter<SOURCE_TYPE, DESTINATION_TYPE> {
  2  
  3      DESTINATION_TYPE convertSource(SOURCE_TYPE sourceValue);
  4  
  5      SOURCE_TYPE convertDestination(DESTINATION_TYPE destinationValue);
  6  }

Das folgende Beispiel implementiert einen Binding Converter, welcher eine Liste in ein Array und zurück konvertiert:

  1  public final class ListArrayBindingConverter implements IBindingConverter<List<String>, String[]> {
  2  
  3      @Override
  4      public String[] convertSource(final List<String> list) {
  5          if (list != null) {
  6              return list.toArray(new String[list.size()]);
  7          }
  8          else {
  9              return null;
 10          }
 11      }
 12  
 13      @Override
 14      public List<String> convertDestination(final String[] destinationValue) {
 15          if (destinationValue != null) {
 16              return new ArrayList<String>(Arrays.asList(destinationValue));
 17          }
 18          else {
 19              return null;
 20          }
 21      }
 22  }

Dieser könnte wie folgt verwendet werden können:

  1      final ObservableValue<List<String>> source = new ObservableValue<List<String>>();
  2      final ObservableValue<String[]> destination = new ObservableValue<String[]>();
  3  
  4      Bind.bind(source, destination, new ListArrayBindingConverter());
Binding Test Beispiel

Der folgende JUnitTest demonstriert die Verwendung der Klasse Bind. Der Test wurde etwas verkürzt, der vollständige Test findet sich hier:

  1  public class BindingTest {
  2  
  3      private static String STRING_1 = "STRING_1";
  4      private static String STRING_2 = "STRING_2";
  5      private static String STRING_3 = "STRING_3";
  6      private static String STRING_4 = "STRING_4";
  7      private static String STRING_5 = "STRING_5";
  8      private static String STRING_6 = "STRING_6";
  9      private static String STRING_7 = "STRING_7";
 10      private static String STRING_8 = "STRING_8";
 11      private static String STRING_9 = "STRING_9";
 12      private static String STRING_10 = "STRING_10";
 13  
 14      @Test
 15      public void testBinding() {
 16          //Create two observable values
 17          final ObservableValue<String> source = new ObservableValue<String>(STRING_1);
 18          final ObservableValue<String> destination = new ObservableValue<String>(STRING_2);
 19  
 20          //create a new binding
 21          final IBinding binding = Bind.bind(source, destination);
 22  
 23          //must be equal and must be STRING_1 (source before binding)
 24          testEquality(source, destination, STRING_1);
 25  
 26          //change source must change destination
 27          source.setValue(STRING_3);
 28  
 29          //must be equal and STRING_3
 30          testEquality(source, destination, STRING_3);
 31  
 32          //change destination must change source
 33          destination.setValue(STRING_4);
 34  
 35          //must be equal and STRING_4
 36          testEquality(source, destination, STRING_4);
 37  
 38          //unbind the values
 39          binding.unbind();
 40  
 41          //after unbind, change source, destination changes not
 42          source.setValue(STRING_5);
 43          Assert.assertEquals(STRING_5, source.getValue());
 44          Assert.assertEquals(STRING_4, destination.getValue());
 45  
 46          //after unbind, change destination, source changes not
 47          destination.setValue(STRING_6);
 48          Assert.assertEquals(STRING_6, destination.getValue());
 49          Assert.assertEquals(STRING_5, source.getValue());
 50  
 51          //bind the values again
 52          binding.bind();
 53  
 54          //must be equal and STRING_5 (last source value)
 55          testEquality(source, destination, STRING_5);
 56      }
 57  
 58      private void testEquality(
 59          final IObservableValue<String> source,
 60          final IObservableValue<String> destination,
 61          final String expectedValue) {
 62  
 63          //the values of the observable value must be equal
 64          Assert.assertEquals(source.getValue(), destination.getValue());
 65  
 66          //the source must be the expected value
 67          Assert.assertEquals(expectedValue, source.getValue());
 68  
 69          //the destination must be the expected value
 70          Assert.assertEquals(expectedValue, destination.getValue());
 71      }
 72  
 73  }

Siehe auch PDF Version dieses Dokuments, Jowidgets API Spezifikation