Loading tools/data-binding/TestApp/src/androidTest/java/com/android/databinding/testapp/com/android/databinding/testapp/vo/ObservableWithNotBindableFieldObjectTest.java 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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.testapp.com.android.databinding.testapp.vo; import com.android.databinding.testapp.BaseDataBinderTest; import com.android.databinding.testapp.R; import com.android.databinding.testapp.generated.ObservableWithNotBindableFieldBinder; import com.android.databinding.testapp.vo.ObservableWithNotBindableFieldObject; import android.test.UiThreadTest; public class ObservableWithNotBindableFieldObjectTest extends BaseDataBinderTest<ObservableWithNotBindableFieldBinder> { public ObservableWithNotBindableFieldObjectTest() { super(ObservableWithNotBindableFieldBinder.class, R.layout.observable_with_not_bindable_field); } @UiThreadTest public void testSimple() { ObservableWithNotBindableFieldObject obj = new ObservableWithNotBindableFieldObject(); mBinder.setObj(obj); mBinder.rebindDirty(); assertEquals("", mBinder.getTextView().getText().toString()); obj.update("100"); mBinder.rebindDirty(); assertEquals("100", mBinder.getTextView().getText().toString()); } } tools/data-binding/TestApp/src/main/java/com/android/databinding/testapp/vo/ObservableWithNotBindableFieldObject.java 0 → 100644 +28 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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.testapp.vo; import com.android.databinding.library.BaseObservable; public class ObservableWithNotBindableFieldObject extends BaseObservable { private String data; public void update(String data) { this.data = data; notifyChange(); } public String getData() { return data; } } tools/data-binding/TestApp/src/main/res/layout/observable_with_not_bindable_field.xml 0 → 100644 +23 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2015 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. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <variable name="obj" type="com.android.databinding.testapp.vo.ObservableWithNotBindableFieldObject"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/text_view" android:text="@{obj.data}"/> </LinearLayout> No newline at end of file tools/data-binding/compiler/src/main/java/com/android/databinding/ClassAnalyzer.java +51 −28 Original line number Diff line number Diff line Loading @@ -54,7 +54,8 @@ public class ClassAnalyzer { OBSERVABLE_CLASS_NAME, "com.android.databinding.MockObservable", BINDABLE_ANNOTATION_NAME, "com.android.databinding.MockBindable", OBSERVABLE_LIST_CLASS_NAME, "com.android.databinding.MockObservableLsit", OBSERVABLE_MAP_CLASS_NAME, "com.android.databinding.MockObservableMap" OBSERVABLE_MAP_CLASS_NAME, "com.android.databinding.MockObservableMap", I_VIEW_DATA_BINDER, "com.android.databinding.MockIViewDataBinder" ); private static ClassAnalyzer sClassAnalyzer; Loading Loading @@ -172,34 +173,25 @@ public class ClassAnalyzer { public Callable findMethodOrField(Class klass, String name) { for (String methodName : new String[]{"get" + StringUtils.capitalize(name), name}) { new String[]{"get" + StringUtils.capitalize(name), "is" + StringUtils.capitalize(name), name}) { try { Method method = klass.getMethod(methodName); Field backingField = findField(klass, name); Field backingField = findField(klass, name, true); if (Modifier.isPublic(method.getModifiers())) { return new Callable(Callable.Type.METHOD, methodName, method.getReturnType(), true, isBindable(method) || (backingField != null && isBindable(backingField)) ); final Callable result = new Callable(Callable.Type.METHOD, methodName, method.getReturnType(), true, isBindable(method) || (backingField != null && isBindable( backingField))); L.d("backing field for %s is %s", result, backingField); return result; } } catch (Throwable t) { } } for (String methodName : new String[]{"is" + StringUtils.capitalize(name), name}) { try { Method method = klass.getMethod(methodName); Field backingField = findField(klass, name); if (Modifier.isPublic(method.getModifiers())) { return new Callable(Callable.Type.METHOD, methodName, method.getReturnType(), true, isBindable(method) || (backingField != null && isBindable(backingField)) ); } } catch (Throwable t) { } } try { Field field = klass.getField(name); Field field = findField(klass, name, false); if (Modifier.isPublic(field.getModifiers())) { return new Callable(Callable.Type.FIELD, name, field.getType(), !Modifier.isFinal(field.getModifiers()) Loading @@ -212,29 +204,49 @@ public class ClassAnalyzer { "cannot find " + name + " in " + klass.getCanonicalName()); } private Field findField(Class klass, String name) { private Field findField(Class klass, String name, boolean allowNonPublic) { try { return klass.getDeclaredField(name); } catch (Throwable t){} return getField(klass, name, allowNonPublic); } catch (NoSuchFieldException e) { } String capitalizedName = StringUtils.capitalize(name); try { return klass.getField("m" + capitalizedName); return getField(klass, "m" + capitalizedName, allowNonPublic); } catch (Throwable t){} try { return klass.getField("_" + name); return getField(klass, "_" + name, allowNonPublic); } catch (Throwable t){} try { return klass.getField("_" + capitalizedName); return getField(klass, "_" + capitalizedName, allowNonPublic); } catch (Throwable t){} try { return klass.getField("m_" + name); return getField(klass, "m_" + name, allowNonPublic); } catch (Throwable t){} try { return klass.getField("m_" + capitalizedName); return getField(klass, "m_" + capitalizedName, allowNonPublic); } catch (Throwable t){} return null; } private Field getField(Class klass, String exactName, boolean allowNonPublic) throws NoSuchFieldException { try { return klass.getField(exactName); } catch (NoSuchFieldException e) { if (allowNonPublic) { return klass.getDeclaredField(exactName); } else { throw e; } } } private Field findField(Class klass, String name) { return findField(klass, name, false); } public Class findCommonParentOf(Class klass1, Class klass2) { Class curr = klass1; while (curr != null && !curr.isAssignableFrom(klass2)) { Loading Loading @@ -392,5 +404,16 @@ public class ClassAnalyzer { public String getTypeCodeName() { return ClassAnalyzer.toCodeName(resolvedType); } @Override public String toString() { return "Callable{" + "type=" + type + ", name='" + name + '\'' + ", resolvedType=" + resolvedType + ", isDynamic=" + isDynamic + ", canBeInvalidated=" + canBeInvalidated + '}'; } } } tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ExprModel.java +12 −9 Original line number Diff line number Diff line Loading @@ -234,8 +234,10 @@ public class ExprModel { continue;// already has some id, means observable } // only fields earn an id if (parent instanceof FieldAccessExpr && parent.isDynamic() && !((FieldAccessExpr) parent).getName().isEmpty()) { if (parent instanceof FieldAccessExpr) { FieldAccessExpr fae = (FieldAccessExpr) parent; L.d("checking field access expr %s. getter: %s", fae,fae.getGetter()); if (fae.isDynamic() && fae.getGetter().canBeInvalidated) { flagMapping.add(parent.getUniqueKey()); parent.setId(counter++); notifiableExpressions.add(parent); Loading @@ -246,6 +248,7 @@ public class ExprModel { } } } } // non-dynamic binding expressions receive some ids so that they can be invalidated for (Expr expr : mBindingExpressions) { Loading Loading
tools/data-binding/TestApp/src/androidTest/java/com/android/databinding/testapp/com/android/databinding/testapp/vo/ObservableWithNotBindableFieldObjectTest.java 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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.testapp.com.android.databinding.testapp.vo; import com.android.databinding.testapp.BaseDataBinderTest; import com.android.databinding.testapp.R; import com.android.databinding.testapp.generated.ObservableWithNotBindableFieldBinder; import com.android.databinding.testapp.vo.ObservableWithNotBindableFieldObject; import android.test.UiThreadTest; public class ObservableWithNotBindableFieldObjectTest extends BaseDataBinderTest<ObservableWithNotBindableFieldBinder> { public ObservableWithNotBindableFieldObjectTest() { super(ObservableWithNotBindableFieldBinder.class, R.layout.observable_with_not_bindable_field); } @UiThreadTest public void testSimple() { ObservableWithNotBindableFieldObject obj = new ObservableWithNotBindableFieldObject(); mBinder.setObj(obj); mBinder.rebindDirty(); assertEquals("", mBinder.getTextView().getText().toString()); obj.update("100"); mBinder.rebindDirty(); assertEquals("100", mBinder.getTextView().getText().toString()); } }
tools/data-binding/TestApp/src/main/java/com/android/databinding/testapp/vo/ObservableWithNotBindableFieldObject.java 0 → 100644 +28 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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.testapp.vo; import com.android.databinding.library.BaseObservable; public class ObservableWithNotBindableFieldObject extends BaseObservable { private String data; public void update(String data) { this.data = data; notifyChange(); } public String getData() { return data; } }
tools/data-binding/TestApp/src/main/res/layout/observable_with_not_bindable_field.xml 0 → 100644 +23 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2015 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. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <variable name="obj" type="com.android.databinding.testapp.vo.ObservableWithNotBindableFieldObject"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/text_view" android:text="@{obj.data}"/> </LinearLayout> No newline at end of file
tools/data-binding/compiler/src/main/java/com/android/databinding/ClassAnalyzer.java +51 −28 Original line number Diff line number Diff line Loading @@ -54,7 +54,8 @@ public class ClassAnalyzer { OBSERVABLE_CLASS_NAME, "com.android.databinding.MockObservable", BINDABLE_ANNOTATION_NAME, "com.android.databinding.MockBindable", OBSERVABLE_LIST_CLASS_NAME, "com.android.databinding.MockObservableLsit", OBSERVABLE_MAP_CLASS_NAME, "com.android.databinding.MockObservableMap" OBSERVABLE_MAP_CLASS_NAME, "com.android.databinding.MockObservableMap", I_VIEW_DATA_BINDER, "com.android.databinding.MockIViewDataBinder" ); private static ClassAnalyzer sClassAnalyzer; Loading Loading @@ -172,34 +173,25 @@ public class ClassAnalyzer { public Callable findMethodOrField(Class klass, String name) { for (String methodName : new String[]{"get" + StringUtils.capitalize(name), name}) { new String[]{"get" + StringUtils.capitalize(name), "is" + StringUtils.capitalize(name), name}) { try { Method method = klass.getMethod(methodName); Field backingField = findField(klass, name); Field backingField = findField(klass, name, true); if (Modifier.isPublic(method.getModifiers())) { return new Callable(Callable.Type.METHOD, methodName, method.getReturnType(), true, isBindable(method) || (backingField != null && isBindable(backingField)) ); final Callable result = new Callable(Callable.Type.METHOD, methodName, method.getReturnType(), true, isBindable(method) || (backingField != null && isBindable( backingField))); L.d("backing field for %s is %s", result, backingField); return result; } } catch (Throwable t) { } } for (String methodName : new String[]{"is" + StringUtils.capitalize(name), name}) { try { Method method = klass.getMethod(methodName); Field backingField = findField(klass, name); if (Modifier.isPublic(method.getModifiers())) { return new Callable(Callable.Type.METHOD, methodName, method.getReturnType(), true, isBindable(method) || (backingField != null && isBindable(backingField)) ); } } catch (Throwable t) { } } try { Field field = klass.getField(name); Field field = findField(klass, name, false); if (Modifier.isPublic(field.getModifiers())) { return new Callable(Callable.Type.FIELD, name, field.getType(), !Modifier.isFinal(field.getModifiers()) Loading @@ -212,29 +204,49 @@ public class ClassAnalyzer { "cannot find " + name + " in " + klass.getCanonicalName()); } private Field findField(Class klass, String name) { private Field findField(Class klass, String name, boolean allowNonPublic) { try { return klass.getDeclaredField(name); } catch (Throwable t){} return getField(klass, name, allowNonPublic); } catch (NoSuchFieldException e) { } String capitalizedName = StringUtils.capitalize(name); try { return klass.getField("m" + capitalizedName); return getField(klass, "m" + capitalizedName, allowNonPublic); } catch (Throwable t){} try { return klass.getField("_" + name); return getField(klass, "_" + name, allowNonPublic); } catch (Throwable t){} try { return klass.getField("_" + capitalizedName); return getField(klass, "_" + capitalizedName, allowNonPublic); } catch (Throwable t){} try { return klass.getField("m_" + name); return getField(klass, "m_" + name, allowNonPublic); } catch (Throwable t){} try { return klass.getField("m_" + capitalizedName); return getField(klass, "m_" + capitalizedName, allowNonPublic); } catch (Throwable t){} return null; } private Field getField(Class klass, String exactName, boolean allowNonPublic) throws NoSuchFieldException { try { return klass.getField(exactName); } catch (NoSuchFieldException e) { if (allowNonPublic) { return klass.getDeclaredField(exactName); } else { throw e; } } } private Field findField(Class klass, String name) { return findField(klass, name, false); } public Class findCommonParentOf(Class klass1, Class klass2) { Class curr = klass1; while (curr != null && !curr.isAssignableFrom(klass2)) { Loading Loading @@ -392,5 +404,16 @@ public class ClassAnalyzer { public String getTypeCodeName() { return ClassAnalyzer.toCodeName(resolvedType); } @Override public String toString() { return "Callable{" + "type=" + type + ", name='" + name + '\'' + ", resolvedType=" + resolvedType + ", isDynamic=" + isDynamic + ", canBeInvalidated=" + canBeInvalidated + '}'; } } }
tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ExprModel.java +12 −9 Original line number Diff line number Diff line Loading @@ -234,8 +234,10 @@ public class ExprModel { continue;// already has some id, means observable } // only fields earn an id if (parent instanceof FieldAccessExpr && parent.isDynamic() && !((FieldAccessExpr) parent).getName().isEmpty()) { if (parent instanceof FieldAccessExpr) { FieldAccessExpr fae = (FieldAccessExpr) parent; L.d("checking field access expr %s. getter: %s", fae,fae.getGetter()); if (fae.isDynamic() && fae.getGetter().canBeInvalidated) { flagMapping.add(parent.getUniqueKey()); parent.setId(counter++); notifiableExpressions.add(parent); Loading @@ -246,6 +248,7 @@ public class ExprModel { } } } } // non-dynamic binding expressions receive some ids so that they can be invalidated for (Expr expr : mBindingExpressions) { Loading