diff --git a/KDataBinder/.idea/uiDesigner.xml b/KDataBinder/.idea/uiDesigner.xml
new file mode 100644
index 0000000000000..e96534fb27b68
--- /dev/null
+++ b/KDataBinder/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/data-binding/annotationprocessor/build.gradle b/tools/data-binding/annotationprocessor/build.gradle
new file mode 100644
index 0000000000000..19c563def5142
--- /dev/null
+++ b/tools/data-binding/annotationprocessor/build.gradle
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+apply plugin: 'java'
+apply plugin: 'maven'
+
+buildscript {
+ repositories {
+ mavenLocal()
+ mavenCentral()
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+sourceSets {
+ main {
+ java {
+ srcDir 'src/main/java'
+ }
+ }
+}
+
+uploadArchives {
+ repositories {
+ mavenDeployer {
+ repository(url: mavenLocal().url)
+ pom.version = '0.1-SNAPSHOT'
+ pom.artifactId = 'annotationprocessor'
+ pom.groupId='com.android.databinding'
+ }
+ }
+}
diff --git a/tools/data-binding/library/src/main/java/com/android/databinding/library/AbsObservable.java b/tools/data-binding/library/src/main/java/com/android/databinding/library/AbsObservable.java
new file mode 100644
index 0000000000000..9a2f4386f36f8
--- /dev/null
+++ b/tools/data-binding/library/src/main/java/com/android/databinding/library/AbsObservable.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.databinding.library;
+
+public abstract class AbsObservable implements Observable {
+ private ChangeListenerRegistry mCallbacks;
+
+ public AbsObservable() {
+ }
+
+ @Override
+ public synchronized void addListener(OnPropertyChangedListener listener) {
+ if (mCallbacks == null) {
+ mCallbacks = new ChangeListenerRegistry();
+ }
+ mCallbacks.add(listener);
+ }
+
+ @Override
+ public synchronized void removeListener(OnPropertyChangedListener listener) {
+ if (mCallbacks != null) {
+ mCallbacks.remove(listener);
+ }
+ }
+
+ public synchronized void notifyChange() {
+ if (mCallbacks != null) {
+ mCallbacks.notifyCallbacks(this, 0);
+ }
+ }
+
+ public synchronized void notifyChange(int id) {
+ if (mCallbacks != null) {
+ mCallbacks.notifyCallbacks(this, id);
+ }
+ }
+}
diff --git a/tools/data-binding/library/src/main/java/com/android/databinding/library/BaseObservable.java b/tools/data-binding/library/src/main/java/com/android/databinding/library/BaseObservable.java
deleted file mode 100644
index 30c4a743122ee..0000000000000
--- a/tools/data-binding/library/src/main/java/com/android/databinding/library/BaseObservable.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.databinding.library;
-
-import java.util.concurrent.CopyOnWriteArraySet;
-
-public class BaseObservable implements Observable {
- final ObservableHelper mHelper;
-
- public BaseObservable() {
- mHelper = new ObservableHelper(this);
- }
-
- @Override
- public void register(ObservableListener listener) {
- mHelper.register(listener);
- }
-
- @Override
- public void unRegister(ObservableListener listener) {
- mHelper.unRegister(listener);
- }
-
- public void fireChange() {
- mHelper.fireChange();
- }
- public void fireChange(String fieldName) {
- mHelper.fireChange(fieldName);
- }
- public void fireChange(int fieldId) {mHelper.fireChange(fieldId);}
-}
diff --git a/tools/data-binding/library/src/main/java/com/android/databinding/library/CallbackRegistry.java b/tools/data-binding/library/src/main/java/com/android/databinding/library/CallbackRegistry.java
new file mode 100644
index 0000000000000..820561f045c6c
--- /dev/null
+++ b/tools/data-binding/library/src/main/java/com/android/databinding/library/CallbackRegistry.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.databinding.library;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tracks callbacks for the event. This class supports reentrant modification
+ * of the callbacks during notification without adversely disrupting notifications.
+ * A common pattern for callbacks is to receive a notification and then remove
+ * themselves. This class handles this behavior with constant memory under
+ * most circumstances.
+ *
+ *
A subclass of {@link com.android.databinding.library.CallbackRegistry.NotifierCallback} must be passed to
+ * the constructor to define how notifications should be called. That implementation
+ * does the actual notification on the listener.
+ *
+ * This class supports only callbacks with at most two parameters.
+ * Typically, these are the notification originator and a parameter, but these may
+ * be used as required. If more than two parameters are required or primitive types
+ * must be used, A should be some kind of containing structure that
+ * the subclass may reuse between notifications.
+ *
+ * @param The callback type.
+ * @param The notification sender type. Typically this is the containing class.
+ */
+public class CallbackRegistry implements Cloneable {
+ private static final String TAG = "CallbackRegistry";
+
+ /** An ordered collection of listeners waiting to be notified. */
+ private List mCallbacks = new ArrayList();
+
+ /**
+ * A bit flag for the first 64 listeners that are removed during notification.
+ * The lowest significant bit corresponds to the 0th index into mCallbacks.
+ * For a small number of callbacks, no additional array of objects needs to
+ * be allocated.
+ */
+ private long mFirst64Removed = 0x0;
+
+ /**
+ * Bit flags for the remaining callbacks that are removed during notification.
+ * When there are more than 64 callbacks and one is marked for removal, a dynamic
+ * array of bits are allocated for the callbacks.
+ */
+ private long[] mRemainderRemoved;
+
+ /** The recursion level of the notification */
+ private int mNotificationLevel;
+
+ /** The notification mechanism for notifying an event. */
+ private final NotifierCallback mNotifier;
+
+ /**
+ * Creates an EventRegistry that notifies the event with notifier.
+ * @param notifier The class to use to notify events.
+ */
+ public CallbackRegistry(NotifierCallback notifier) {
+ mNotifier = notifier;
+ }
+
+ /**
+ * Notify all callbacks.
+ *
+ * @param sender The originator. This is an opaque parameter passed to
+ * {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
+ * @param arg An opaque parameter passed to
+ * {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
+ */
+ public synchronized void notifyCallbacks(T sender, int arg) {
+ mNotificationLevel++;
+ notifyRecurse(sender, arg);
+ mNotificationLevel--;
+ if (mNotificationLevel == 0) {
+ if (mRemainderRemoved != null) {
+ for (int i = mRemainderRemoved.length - 1; i >= 0; i--) {
+ final long removedBits = mRemainderRemoved[i];
+ if (removedBits != 0) {
+ removeRemovedCallbacks((i + 1) * Long.SIZE, removedBits);
+ mRemainderRemoved[i] = 0;
+ }
+ }
+ }
+ if (mFirst64Removed != 0) {
+ removeRemovedCallbacks(0, mFirst64Removed);
+ mFirst64Removed = 0;
+ }
+ }
+ }
+
+ /**
+ * Notify up to the first Long.SIZE callbacks that don't have a bit set in removed.
+ *
+ * @param sender The originator. This is an opaque parameter passed to
+ * {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
+ * @param arg An opaque parameter passed to
+ * {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
+ */
+ private void notifyFirst64(T sender, int arg) {
+ final int maxNotified = Math.min(Long.SIZE, mCallbacks.size());
+ notifyCallbacks(sender, arg, 0, maxNotified, mFirst64Removed);
+ }
+
+ /**
+ * Notify all callbacks using a recursive algorithm to avoid allocating on the heap.
+ * This part captures the callbacks beyond Long.SIZE that have no bits allocated for
+ * removal before it recurses into {@link #notifyRemainder(Object, int, int)}.
+ *
+ * Recursion is used to avoid allocating temporary state on the heap.
+ *
+ * @param sender The originator. This is an opaque parameter passed to
+ * {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
+ * @param arg An opaque parameter passed to
+ * {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
+ */
+ private void notifyRecurse(T sender, int arg) {
+ final int callbackCount = mCallbacks.size();
+ final int remainderIndex = mRemainderRemoved == null ? -1 : mRemainderRemoved.length - 1;
+
+ // Now we've got all callbakcs that have no mRemainderRemoved value, so notify the
+ // others.
+ notifyRemainder(sender, arg, remainderIndex);
+
+ // notifyRemainder notifies all at maxIndex, so we'd normally start at maxIndex + 1
+ // However, we must also keep track of those in mFirst64Removed, so we add 2 instead:
+ final int startCallbackIndex = (remainderIndex + 2) * Long.SIZE;
+
+ // The remaining have no bit set
+ notifyCallbacks(sender, arg, startCallbackIndex, callbackCount, 0);
+ }
+
+ /**
+ * Notify callbacks that have mRemainderRemoved bits set for remainderIndex. If
+ * remainderIndex is -1, the first 64 will be notified instead.
+ *
+ * @param sender The originator. This is an opaque parameter passed to
+ * {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
+ * @param arg An opaque parameter passed to
+ * {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
+ * @param remainderIndex The index into mRemainderRemoved that should be notified.
+ */
+ private void notifyRemainder(T sender, int arg, int remainderIndex) {
+ if (remainderIndex < 0) {
+ notifyFirst64(sender, arg);
+ } else {
+ final long bits = mRemainderRemoved[remainderIndex];
+ final int startIndex = (remainderIndex + 1) * Long.SIZE;
+ final int endIndex = Math.min(mCallbacks.size(), startIndex + Long.SIZE);
+ notifyRemainder(sender, arg, remainderIndex - 1);
+ notifyCallbacks(sender, arg, startIndex, endIndex, bits);
+ }
+ }
+
+ /**
+ * Notify callbacks from startIndex to endIndex, using bits as the bit status
+ * for whether they have been removed or not. bits should be from mRemainderRemoved or
+ * mFirst64Removed. bits set to 0 indicates that all callbacks from startIndex to
+ * endIndex should be notified.
+ *
+ * @param sender The originator. This is an opaque parameter passed to
+ * {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
+ * @param arg An opaque parameter passed to
+ * {@link com.android.databinding.library.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int)}
+ * @param startIndex The index into the mCallbacks to start notifying.
+ * @param endIndex One past the last index into mCallbacks to notify.
+ * @param bits A bit field indicating which callbacks have been removed and shouldn't
+ * be notified.
+ */
+ private void notifyCallbacks(T sender, int arg, final int startIndex, final int endIndex,
+ final long bits) {
+ long bitMask = 1;
+ for (int i = startIndex; i < endIndex; i++) {
+ if ((bits & bitMask) == 0) {
+ mNotifier.onNotifyCallback(mCallbacks.get(i), sender, arg);
+ }
+ bitMask <<= 1;
+ }
+ }
+
+ /**
+ * Add a callback to be notified. If the callback is already in the list, another won't
+ * be added. This does not affect current notifications.
+ * @param callback The callback to add.
+ */
+ public synchronized void add(C callback) {
+ int index = mCallbacks.lastIndexOf(callback);
+ if (index < 0 || isRemoved(index)) {
+ mCallbacks.add(callback);
+ }
+ }
+
+ /**
+ * Returns true if the callback at index has been marked for removal.
+ *
+ * @param index The index into mCallbacks to check.
+ * @return true if the callback at index has been marked for removal.
+ */
+ private boolean isRemoved(int index) {
+ if (index < Long.SIZE) {
+ // It is in the first 64 callbacks, just check the bit.
+ final long bitMask = 1L << index;
+ return (mFirst64Removed & bitMask) != 0;
+ } else if (mRemainderRemoved == null) {
+ // It is after the first 64 callbacks, but nothing else was marked for removal.
+ return false;
+ } else {
+ final int maskIndex = (index / Long.SIZE) - 1;
+ if (maskIndex >= mRemainderRemoved.length) {
+ // There are some items in mRemainderRemoved, but nothing at the given index.
+ return false;
+ } else {
+ // There is something marked for removal, so we have to check the bit.
+ final long bits = mRemainderRemoved[maskIndex];
+ final long bitMask = 1L << (index % Long.SIZE);
+ return (bits & bitMask) != 0;
+ }
+ }
+ }
+
+ /**
+ * Removes callbacks from startIndex to startIndex + Long.SIZE, based
+ * on the bits set in removed.
+ * @param startIndex The index into the mCallbacks to start removing callbacks.
+ * @param removed The bits indicating removal, where each bit is set for one callback
+ * to be removed.
+ */
+ private void removeRemovedCallbacks(int startIndex, long removed) {
+ // The naive approach should be fine. There may be a better bit-twiddling approach.
+ final int endIndex = startIndex + Long.SIZE;
+
+ long bitMask = 1L << (Long.SIZE - 1);
+ for (int i = endIndex - 1; i >= startIndex; i--) {
+ if ((removed & bitMask) != 0) {
+ mCallbacks.remove(i);
+ }
+ bitMask >>>= 1;
+ }
+ }
+
+ /**
+ * Remove a callback. This callback won't be notified after this call completes.
+ * @param callback The callback to remove.
+ */
+ public synchronized void remove(C callback) {
+ if (mNotificationLevel == 0) {
+ mCallbacks.remove(callback);
+ } else {
+ int index = mCallbacks.lastIndexOf(callback);
+ if (index >= 0) {
+ setRemovalBit(index);
+ }
+ }
+ }
+
+ private void setRemovalBit(int index) {
+ if (index < Long.SIZE) {
+ // It is in the first 64 callbacks, just check the bit.
+ final long bitMask = 1L << index;
+ mFirst64Removed |= bitMask;
+ } else {
+ final int remainderIndex = (index / Long.SIZE) - 1;
+ if (mRemainderRemoved == null) {
+ mRemainderRemoved = new long[mCallbacks.size() / Long.SIZE];
+ } else if (mRemainderRemoved.length < remainderIndex) {
+ // need to make it bigger
+ long[] newRemainders = new long[mCallbacks.size() / Long.SIZE];
+ System.arraycopy(mRemainderRemoved, 0, newRemainders, 0, mRemainderRemoved.length);
+ mRemainderRemoved = newRemainders;
+ }
+ final long bitMask = 1L << (index % Long.SIZE);
+ mRemainderRemoved[remainderIndex] |= bitMask;
+ }
+ }
+
+ /*
+ private void clearRemovalBit(int index) {
+ if (index < Long.SIZE) {
+ // It is in the first 64 callbacks, just check the bit.
+ final long bitMask = 1L << index;
+ mFirst64Removed &= ~bitMask;
+ } else if (mRemainderRemoved != null) {
+ final int maskIndex = (index / Long.SIZE) - 1;
+ if (maskIndex < mRemainderRemoved.length) {
+ // There is something marked for removal, so we have to check the bit.
+ final long bitMask = 1L << (index % Long.SIZE);
+ mRemainderRemoved[maskIndex] &= ~bitMask;
+ }
+ }
+ }
+ */
+
+ /**
+ * Makes a copy of the registered callbacks and returns it.
+ *
+ * @return a copy of the registered callbacks.
+ */
+ public synchronized ArrayList copyListeners() {
+ ArrayList callbacks = new ArrayList(mCallbacks.size());
+ int numListeners = mCallbacks.size();
+ for (int i = 0; i < numListeners; i++) {
+ if (!isRemoved(i)) {
+ callbacks.add(mCallbacks.get(i));
+ }
+ }
+ return callbacks;
+ }
+
+ /**
+ * Returns true if there are no registered callbacks or false otherwise.
+ *
+ * @return true if there are no registered callbacks or false otherwise.
+ */
+ public synchronized boolean isEmpty() {
+ if (mCallbacks.isEmpty()) {
+ return true;
+ } else if (mNotificationLevel == 0) {
+ return false;
+ } else {
+ int numListeners = mCallbacks.size();
+ for (int i = 0; i < numListeners; i++) {
+ if (!isRemoved(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Removes all callbacks from the list.
+ */
+ public synchronized void clear() {
+ if (mNotificationLevel == 0) {
+ mCallbacks.clear();
+ } else if (!mCallbacks.isEmpty()) {
+ for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+ setRemovalBit(i);
+ }
+ }
+ }
+
+ public synchronized CallbackRegistry clone() {
+ CallbackRegistry clone = null;
+ try {
+ clone = (CallbackRegistry) super.clone();
+ clone.mFirst64Removed = 0;
+ clone.mRemainderRemoved = null;
+ clone.mNotificationLevel = 0;
+ clone.mCallbacks = new ArrayList();
+ final int numListeners = mCallbacks.size();
+ for (int i = 0; i < numListeners; i++) {
+ if (!isRemoved(i)) {
+ clone.mCallbacks.add(mCallbacks.get(i));
+ }
+ }
+ } catch (CloneNotSupportedException e) {
+ Log.e(TAG, "Could not clone CallbackRegistry", e);
+ }
+ return clone;
+ }
+
+ /**
+ * Class used to notify events from CallbackRegistry.
+ *
+ * @param The callback type.
+ * @param The notification sender type. Typically this is the containing class.
+ */
+ public abstract static class NotifierCallback {
+ /**
+ * Used to notify the callback.
+ *
+ * @param callback The callback to notify.
+ * @param sender The opaque sender object.
+ * @param arg The opaque notification parameter.
+ * @see CallbackRegistry#CallbackRegistry(com.android.databinding.library.CallbackRegistry.NotifierCallback)
+ */
+ public abstract void onNotifyCallback(C callback, T sender, int arg);
+ }
+}
diff --git a/tools/data-binding/library/src/main/java/com/android/databinding/library/ChangeListenerRegistry.java b/tools/data-binding/library/src/main/java/com/android/databinding/library/ChangeListenerRegistry.java
new file mode 100644
index 0000000000000..46de74391474d
--- /dev/null
+++ b/tools/data-binding/library/src/main/java/com/android/databinding/library/ChangeListenerRegistry.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.databinding.library;
+
+/**
+ * Created by mount on 12/15/14.
+ */
+public class ChangeListenerRegistry extends
+ CallbackRegistry {
+
+ private static final CallbackRegistry.NotifierCallback NOTIFIER_CALLBACK = new CallbackRegistry.NotifierCallback() {
+ @Override
+ public void onNotifyCallback(OnPropertyChangedListener callback, Observable sender,
+ int arg) {
+ callback.onPropertyChanged(arg);
+ }
+ };
+
+ public ChangeListenerRegistry() {
+ super(NOTIFIER_CALLBACK);
+ }
+}
diff --git a/tools/data-binding/library/src/main/java/com/android/databinding/library/Observable.java b/tools/data-binding/library/src/main/java/com/android/databinding/library/Observable.java
index e825dd59c73a6..59ffd0e5bd463 100644
--- a/tools/data-binding/library/src/main/java/com/android/databinding/library/Observable.java
+++ b/tools/data-binding/library/src/main/java/com/android/databinding/library/Observable.java
@@ -17,6 +17,6 @@
package com.android.databinding.library;
public interface Observable {
- public void register(ObservableListener listener);
- public void unRegister(ObservableListener listener);
+ public void addListener(OnPropertyChangedListener listener);
+ public void removeListener(OnPropertyChangedListener listener);
}
diff --git a/tools/data-binding/library/src/main/java/com/android/databinding/library/ObservableHelper.java b/tools/data-binding/library/src/main/java/com/android/databinding/library/ObservableHelper.java
deleted file mode 100644
index bac5686d9a9ca..0000000000000
--- a/tools/data-binding/library/src/main/java/com/android/databinding/library/ObservableHelper.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.databinding.library;
-
-import java.util.concurrent.CopyOnWriteArraySet;
-
-public class ObservableHelper implements Observable {
- final Observable owner;
- CopyOnWriteArraySet mListeners;
-
- public ObservableHelper(Observable owner) {
- this.owner = owner;
- }
-
- private synchronized CopyOnWriteArraySet getListeners(boolean createIfMissing) {
- if (mListeners == null) {
- if (createIfMissing) {
- mListeners = new CopyOnWriteArraySet<>();
- }
- }
- return mListeners;
- }
-
- public void fireChange() {
- fireChange("");
- }
- public void fireChange(String fieldName) {
- fireChange(DataBinder.convertToId(fieldName));
- }
- public void fireChange(int fieldId) {
- final CopyOnWriteArraySet listeners = getListeners(false);
- if (listeners == null) {
- return;
- }
- for (ObservableListener listener : listeners) {
- listener.onChange(fieldId);
- }
- }
-
- @Override
- public void register(ObservableListener listener) {
- getListeners(true).add(listener);
- }
-
- @Override
- public void unRegister(ObservableListener listener) {
- final CopyOnWriteArraySet listeners = getListeners(false);
- if (listener != null) {
- listeners.remove(listener);
- }
- }
-}
diff --git a/tools/data-binding/library/src/main/java/com/android/databinding/library/ObservableListener.java b/tools/data-binding/library/src/main/java/com/android/databinding/library/OnPropertyChangedListener.java
similarity index 86%
rename from tools/data-binding/library/src/main/java/com/android/databinding/library/ObservableListener.java
rename to tools/data-binding/library/src/main/java/com/android/databinding/library/OnPropertyChangedListener.java
index 04ccd381098f4..eab1e9cd9f1bf 100644
--- a/tools/data-binding/library/src/main/java/com/android/databinding/library/ObservableListener.java
+++ b/tools/data-binding/library/src/main/java/com/android/databinding/library/OnPropertyChangedListener.java
@@ -16,7 +16,6 @@
package com.android.databinding.library;
-public interface ObservableListener {
- public void onChange();
- public void onChange(int fieldId);
+public interface OnPropertyChangedListener {
+ public void onPropertyChanged(int fieldId);
}
diff --git a/tools/data-binding/library/src/main/java/com/android/databinding/library/ViewDataBinder.java b/tools/data-binding/library/src/main/java/com/android/databinding/library/ViewDataBinder.java
index f1a3bf5021132..c0ac85cb0c6e1 100644
--- a/tools/data-binding/library/src/main/java/com/android/databinding/library/ViewDataBinder.java
+++ b/tools/data-binding/library/src/main/java/com/android/databinding/library/ViewDataBinder.java
@@ -16,16 +16,11 @@
package com.android.databinding.library;
-import android.util.SparseIntArray;
import android.view.View;
import java.lang.Override;
import java.lang.Runnable;
import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
abstract public class ViewDataBinder {
WeakReferencedListener[] mLocalFieldObservers;
@@ -112,7 +107,7 @@ abstract public class ViewDataBinder {
listener.setTarget(observable);
}
- protected abstract class WeakReferencedListener implements ObservableListener {
+ protected abstract class WeakReferencedListener implements OnPropertyChangedListener {
WeakReference mTarget;
public WeakReferencedListener() {
@@ -121,7 +116,7 @@ abstract public class ViewDataBinder {
public void setTarget(Observable observable) {
if (observable != null) {
mTarget = new WeakReference<>(observable);
- observable.register(this);
+ observable.addListener(this);
} else {
mTarget = null;
}
@@ -130,7 +125,7 @@ abstract public class ViewDataBinder {
public boolean unregister() {
Observable oldTarget = getTarget();
if (oldTarget != null) {
- oldTarget.unRegister(this);
+ oldTarget.removeListener(this);
}
mTarget = null;
return oldTarget != null;
@@ -148,16 +143,7 @@ abstract public class ViewDataBinder {
}
@Override
- public void onChange() {
- Observable obj = getTarget();
- if (obj == null) {
- return;//how come i live if it died ?
- }
- ViewDataBinder.this.handleFieldChange(mLocalFieldId, obj, 0);
- }
-
- @Override
- public void onChange(int fieldId) {
+ public void onPropertyChanged(int fieldId) {
Observable obj = getTarget();
if (obj == null) {
return;//how come i live if it died ?
diff --git a/tools/data-binding/samples/BindingDemo/app/build.gradle b/tools/data-binding/samples/BindingDemo/app/build.gradle
index 45e7ebebfffcb..2347998c85494 100644
--- a/tools/data-binding/samples/BindingDemo/app/build.gradle
+++ b/tools/data-binding/samples/BindingDemo/app/build.gradle
@@ -17,6 +17,8 @@
apply plugin: 'com.android.application'
apply plugin: 'com.android.databinding'
+def generatedSources = "$buildDir/generated/source/br"
+
android {
compileSdkVersion 21
buildToolsVersion "21.1.1"
@@ -38,6 +40,19 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
+ sourceSets {
+ //main.java.srcDirs += generatedSources
+ }
+}
+
+android.applicationVariants.all { variant ->
+ variant.javaCompile.doFirst {
+ println "*** compile doFirst ${variant.name}"
+ new File(generatedSources).mkdirs()
+ variant.javaCompile.options.compilerArgs += [
+ '-s', generatedSources
+ ]
+ }
}
dependencies {
@@ -47,4 +62,5 @@ dependencies {
compile 'com.android.support:recyclerview-v7:21.0.2'
compile 'com.android.support:gridlayout-v7:21+'
compile 'com.android.support:cardview-v7:21.0.2'
+ provided 'com.android.databinding:annotationprocessor:0.1-SNAPSHOT'
}
diff --git a/tools/data-binding/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java b/tools/data-binding/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java
index 51b1c9077c34d..02f3d7bc01354 100644
--- a/tools/data-binding/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java
+++ b/tools/data-binding/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java
@@ -1,5 +1,6 @@
package com.android.example.bindingdemo;
+import android.binding.Bindable;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
@@ -9,15 +10,14 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import com.android.example.bindingdemo.generated.BR;
+import com.android.databinding.library.ChangeListenerRegistry;
+import com.android.databinding.library.Observable;
+import com.android.databinding.library.OnPropertyChangedListener;
import com.android.example.bindingdemo.generated.ListItemBinder;
import com.android.example.bindingdemo.generated.MainActivityBinder;
import com.android.example.bindingdemo.vo.User;
import com.android.example.bindingdemo.vo.Users;
import com.android.databinding.library.DataBinder;
-import com.android.databinding.library.Observable;
-import com.android.databinding.library.ObservableHelper;
-import com.android.databinding.library.ObservableListener;
import java.util.ArrayList;
import java.util.Arrays;
@@ -28,13 +28,13 @@ public class MainActivity extends ActionBarActivity implements Observable {
UserAdapter tkAdapter;
UserAdapter robotAdapter;
MainActivityBinder dataBinder;
+ @Bindable
User selected;
- ObservableHelper helper;
+ ChangeListenerRegistry mChangeListeners = new ChangeListenerRegistry();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- helper = new ObservableHelper(this);
dataBinder = DataBinder.createBinder(MainActivityBinder.class, this, R.layout.main_activity, null);
setContentView(dataBinder.getRoot());
dataBinder.getRobotList().setHasFixedSize(true);
@@ -64,7 +64,7 @@ public class MainActivity extends ActionBarActivity implements Observable {
return;
}
this.selected = selected;
- helper.fireChange(BR.selected);
+ mChangeListeners.notifyCallbacks(this, android.binding.BR.selected);
}
public View.OnClickListener onSave = new View.OnClickListener() {
@@ -130,21 +130,20 @@ public class MainActivity extends ActionBarActivity implements Observable {
}
@Override
- public void register(ObservableListener observableListener) {
- helper.register(observableListener);
+ public void addListener(OnPropertyChangedListener onPropertyChangedListener) {
+ mChangeListeners.add(onPropertyChangedListener);
}
@Override
- public void unRegister(ObservableListener observableListener) {
- helper.unRegister(observableListener);
+ public void removeListener(OnPropertyChangedListener onPropertyChangedListener) {
+ mChangeListeners.remove(onPropertyChangedListener);
}
public class UserAdapter extends DataBoundAdapter implements View.OnClickListener, Observable {
- List userList = new ArrayList<>();
- ObservableHelper mHelper;
+ List userList = new ArrayList();
+ ChangeListenerRegistry mChangeListeners = new ChangeListenerRegistry();
public UserAdapter(User[] toolkities) {
super(R.layout.list_item, ListItemBinder.class);
- mHelper = new ObservableHelper(this);
userList.addAll(Arrays.asList(toolkities));
}
@@ -162,6 +161,7 @@ public class MainActivity extends ActionBarActivity implements Observable {
}
@Override
+ @Bindable
public int getItemCount() {
return userList.size();
}
@@ -172,7 +172,7 @@ public class MainActivity extends ActionBarActivity implements Observable {
}
userList.add(user);
notifyItemInserted(userList.size() - 1);
- mHelper.fireChange("itemCount");
+ mChangeListeners.notifyCallbacks(this, android.binding.BR.itemCount);
}
public void remove(User user) {
@@ -182,7 +182,7 @@ public class MainActivity extends ActionBarActivity implements Observable {
}
userList.remove(i);
notifyItemRemoved(i);
- mHelper.fireChange("itemCount");
+ mChangeListeners.notifyCallbacks(this, android.binding.BR.itemCount);
}
@Override
@@ -198,13 +198,13 @@ public class MainActivity extends ActionBarActivity implements Observable {
}
@Override
- public void register(ObservableListener observableListener) {
- mHelper.register(observableListener);
+ public void addListener(OnPropertyChangedListener onPropertyChangedListener) {
+ mChangeListeners.add(onPropertyChangedListener);
}
@Override
- public void unRegister(ObservableListener observableListener) {
- mHelper.unRegister(observableListener);
+ public void removeListener(OnPropertyChangedListener onPropertyChangedListener) {
+ mChangeListeners.remove(onPropertyChangedListener);
}
}
}
diff --git a/tools/data-binding/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java b/tools/data-binding/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java
index 091dc5c3ac54e..8ea225de1f6bd 100644
--- a/tools/data-binding/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java
+++ b/tools/data-binding/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java
@@ -1,17 +1,23 @@
package com.android.example.bindingdemo.vo;
+import android.binding.Bindable;
import android.graphics.Color;
-import com.android.databinding.library.BaseObservable;
+import com.android.databinding.library.AbsObservable;
import java.util.Objects;
-public class User extends BaseObservable {
+public class User extends AbsObservable {
+ @Bindable
private String name;
+ @Bindable
private String lastName;
+ @Bindable
private int photoResource = 0;
private int favoriteColor = Color.RED;
+ @Bindable
private int group;
+
public static final int TOOLKITTY = 1;
public static final int ROBOT = 2;
@@ -27,7 +33,7 @@ public class User extends BaseObservable {
return;
}
this.group = group;
- fireChange("group");
+ notifyChange(android.binding.BR.group);
}
public int getGroup() {
@@ -43,7 +49,7 @@ public class User extends BaseObservable {
return;
}
this.name = name;
- fireChange("name");
+ notifyChange(android.binding.BR.name);
}
public String getLastName() {
@@ -55,7 +61,7 @@ public class User extends BaseObservable {
return;
}
this.lastName = lastName;
- fireChange("lastName");
+ notifyChange(android.binding.BR.lastName);
}
public int getPhotoResource() {
@@ -67,7 +73,7 @@ public class User extends BaseObservable {
return;
}
this.photoResource = photoResource;
- fireChange("photoResource");
+ notifyChange(android.binding.BR.photoResource);
}
public int getFavoriteColor() {
diff --git a/tools/data-binding/samples/BindingDemo/gradle/wrapper/gradle-wrapper.properties b/tools/data-binding/samples/BindingDemo/gradle/wrapper/gradle-wrapper.properties
index ddbd613051deb..1d32c67555698 100644
--- a/tools/data-binding/samples/BindingDemo/gradle/wrapper/gradle-wrapper.properties
+++ b/tools/data-binding/samples/BindingDemo/gradle/wrapper/gradle-wrapper.properties
@@ -1,22 +1,6 @@
-#
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-#Wed Apr 10 15:27:10 PDT 2013
+#Mon Dec 15 15:24:30 PST 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
diff --git a/tools/data-binding/settings.gradle b/tools/data-binding/settings.gradle
index c069a5794bab5..e1f91a6bced84 100644
--- a/tools/data-binding/settings.gradle
+++ b/tools/data-binding/settings.gradle
@@ -1,4 +1,4 @@
-include ':library'
+include ':library', ':annotationprocessor'
include ':compiler'
include ':gradlePlugin'
-include ':grammerBuilder'
\ No newline at end of file
+include ':grammerBuilder'