Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b389318b authored by George Mount's avatar George Mount
Browse files

Added support for Observable fields.

Added support for ObservableField and it primitive siblings.

Bug 19268016

Change-Id: I28322e5adc44d40013e876271e7d40010c2fe0bb
parent 3d612724
Loading
Loading
Loading
Loading
+144 −0
Original line number Original line 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;

import com.android.databinding.testapp.generated.ObservableFieldTestBinder;
import com.android.databinding.testapp.vo.ObservableFieldBindingObject;

import android.test.UiThreadTest;
import android.widget.TextView;

public class ObservableFieldTest extends BaseDataBinderTest<ObservableFieldTestBinder> {
    private ObservableFieldBindingObject mObj;

    public ObservableFieldTest() {
        super(ObservableFieldTestBinder.class, R.layout.observable_field_test);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        try {
            runTestOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mObj = new ObservableFieldBindingObject();
                    mBinder.setObj(mObj);
                    mBinder.rebindDirty();
                }
            });
        } catch (Throwable throwable) {
            throw new Exception(throwable);
        }
    }

    @UiThreadTest
    public void testBoolean() {
        TextView view = mBinder.getBField();
        assertEquals("false", view.getText());

        mObj.bField.set(true);
        mBinder.rebindDirty();

        assertEquals("true", view.getText());
    }

    @UiThreadTest
    public void testByte() {
        TextView view = mBinder.getTField();
        assertEquals("0", view.getText());

        mObj.tField.set((byte) 1);
        mBinder.rebindDirty();

        assertEquals("1", view.getText());
    }

    @UiThreadTest
    public void testShort() {
        TextView view = mBinder.getSField();
        assertEquals("0", view.getText());

        mObj.sField.set((short) 1);
        mBinder.rebindDirty();

        assertEquals("1", view.getText());
    }

    @UiThreadTest
    public void testChar() {
        TextView view = mBinder.getCField();
        assertEquals("\u0000", view.getText());

        mObj.cField.set('A');
        mBinder.rebindDirty();

        assertEquals("A", view.getText());
    }

    @UiThreadTest
    public void testInt() {
        TextView view = mBinder.getIField();
        assertEquals("0", view.getText());

        mObj.iField.set(1);
        mBinder.rebindDirty();

        assertEquals("1", view.getText());
    }

    @UiThreadTest
    public void testLong() {
        TextView view = mBinder.getLField();
        assertEquals("0", view.getText());

        mObj.lField.set(1);
        mBinder.rebindDirty();

        assertEquals("1", view.getText());
    }

    @UiThreadTest
    public void testFloat() {
        TextView view = mBinder.getFField();
        assertEquals("0.0", view.getText());

        mObj.fField.set(1);
        mBinder.rebindDirty();

        assertEquals("1.0", view.getText());
    }

    @UiThreadTest
    public void testDouble() {
        TextView view = mBinder.getDField();
        assertEquals("0.0", view.getText());

        mObj.dField.set(1);
        mBinder.rebindDirty();

        assertEquals("1.0", view.getText());
    }

    @UiThreadTest
    public void testObject() {
        TextView view = mBinder.getOField();
        assertEquals("Hello", view.getText());

        mObj.oField.set("World");
        mBinder.rebindDirty();

        assertEquals("World", view.getText());
    }
}
+45 −0
Original line number Original line 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;
import com.android.databinding.library.ObservableBoolean;
import com.android.databinding.library.ObservableByte;
import com.android.databinding.library.ObservableChar;
import com.android.databinding.library.ObservableDouble;
import com.android.databinding.library.ObservableField;
import com.android.databinding.library.ObservableFloat;
import com.android.databinding.library.ObservableInt;
import com.android.databinding.library.ObservableLong;
import com.android.databinding.library.ObservableShort;

import android.binding.Bindable;

public class ObservableFieldBindingObject {
    public final ObservableBoolean bField = new ObservableBoolean();
    public final ObservableByte tField = new ObservableByte();
    public final ObservableShort sField = new ObservableShort();
    public final ObservableChar cField = new ObservableChar();
    public final ObservableInt iField = new ObservableInt();
    public final ObservableLong lField = new ObservableLong();
    public final ObservableFloat fField = new ObservableFloat();
    public final ObservableDouble dField = new ObservableDouble();
    public final ObservableField<String> oField = new ObservableField<>();

    public ObservableFieldBindingObject() {
        oField.set("Hello");
    }
}
+52 −0
Original line number Original line Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<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.ObservableFieldBindingObject"/>
    <TextView
            android:id="@+id/bField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{`` + obj.bField}"/>
    <TextView
            android:id="@+id/tField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{`` + obj.tField}"/>
    <TextView
            android:id="@+id/sField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{`` + obj.sField}"/>
    <TextView
            android:id="@+id/cField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{`` + obj.cField}"/>
    <TextView
            android:id="@+id/iField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{`` + obj.iField}"/>
    <TextView
            android:id="@+id/lField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{`` + obj.lField}"/>
    <TextView
            android:id="@+id/fField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{`` + obj.fField}"/>
    <TextView
            android:id="@+id/dField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{`` + obj.dField}"/>
    <TextView
            android:id="@+id/oField"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{obj.oField}"/>
</LinearLayout>
 No newline at end of file
+33 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,17 @@ public class ClassAnalyzer {
    private static final String OBSERVABLE_LIST_CLASS_NAME = "android.binding.ObservableList";
    private static final String OBSERVABLE_LIST_CLASS_NAME = "android.binding.ObservableList";
    private static final String OBSERVABLE_MAP_CLASS_NAME = "android.binding.ObservableMap";
    private static final String OBSERVABLE_MAP_CLASS_NAME = "android.binding.ObservableMap";
    private static final String BINDABLE_ANNOTATION_NAME = "android.binding.Bindable";
    private static final String BINDABLE_ANNOTATION_NAME = "android.binding.Bindable";
    private static final String[] OBSERVABLE_FIELDS = {
            "com.android.databinding.library.ObservableBoolean",
            "com.android.databinding.library.ObservableByte",
            "com.android.databinding.library.ObservableChar",
            "com.android.databinding.library.ObservableShort",
            "com.android.databinding.library.ObservableInt",
            "com.android.databinding.library.ObservableLong",
            "com.android.databinding.library.ObservableFloat",
            "com.android.databinding.library.ObservableDouble",
            "com.android.databinding.library.ObservableField",
    };
    private static final String I_VIEW_DATA_BINDER = "com.android.databinding.library.IViewDataBinder";
    private static final String I_VIEW_DATA_BINDER = "com.android.databinding.library.IViewDataBinder";


    private static Map<String, String> sTestClassNameMapping = ImmutableMap.of(
    private static Map<String, String> sTestClassNameMapping = ImmutableMap.of(
@@ -60,6 +71,8 @@ public class ClassAnalyzer {


    private final Class mObservableMap;
    private final Class mObservableMap;


    private final Class[] mObservableFields;

    private final Class mBindable;
    private final Class mBindable;


    private final boolean mTestMode;
    private final boolean mTestMode;
@@ -75,6 +88,11 @@ public class ClassAnalyzer {
            mObservableList = classLoader.loadClass(getClassName(OBSERVABLE_LIST_CLASS_NAME));
            mObservableList = classLoader.loadClass(getClassName(OBSERVABLE_LIST_CLASS_NAME));
            mObservableMap = classLoader.loadClass(getClassName(OBSERVABLE_MAP_CLASS_NAME));
            mObservableMap = classLoader.loadClass(getClassName(OBSERVABLE_MAP_CLASS_NAME));
            mBindable = classLoader.loadClass(getClassName(BINDABLE_ANNOTATION_NAME));
            mBindable = classLoader.loadClass(getClassName(BINDABLE_ANNOTATION_NAME));
            mObservableFields = new Class[OBSERVABLE_FIELDS.length];
            for (int i = 0; i < OBSERVABLE_FIELDS.length; i++) {
                mObservableFields[i] = classLoader.loadClass(getClassName(OBSERVABLE_FIELDS[i]));
            }

        } catch (ClassNotFoundException e) {
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
            throw new RuntimeException(e);
        }
        }
@@ -134,6 +152,15 @@ public class ClassAnalyzer {
            mObservableMap.isAssignableFrom(klass);
            mObservableMap.isAssignableFrom(klass);
    }
    }


    public boolean isObservableField(Class klass) {
        for (Class observableField : mObservableFields) {
            if (observableField.isAssignableFrom(klass)) {
                return true;
            }
        }
        return false;
    }

    public boolean isBindable(Field field) {
    public boolean isBindable(Field field) {
        return field.getAnnotation(mBindable) != null;
        return field.getAnnotation(mBindable) != null;
    }
    }
@@ -270,6 +297,12 @@ public class ClassAnalyzer {
        if("boolean".equals(className)) {
        if("boolean".equals(className)) {
            return "false";
            return "false";
        }
        }
        if ("char".equals(className)) {
            return "'\\u0000'";
        }
        if ("byte".equals(className)) {
            return "0";
        }
        return "null";
        return "null";
    }
    }


+5 −11
Original line number Original line Diff line number Diff line
@@ -29,21 +29,15 @@ public class BracketExpr extends Expr {
        MAP,
        MAP,
    }
    }


    final private Expr mTarget;

    final private Expr mArg;

    private BracketAccessor mAccessor;
    private BracketAccessor mAccessor;


    BracketExpr(Expr target, Expr arg) {
    BracketExpr(Expr target, Expr arg) {
        super(target, arg);
        super(target, arg);
        mTarget = target;
        mArg = arg;
    }
    }


    @Override
    @Override
    protected Class resolveType(ClassAnalyzer classAnalyzer) {
    protected Class resolveType(ClassAnalyzer classAnalyzer) {
        Class<?> targetType = mTarget.resolveType(classAnalyzer);
        Class<?> targetType = getTarget().resolveType(classAnalyzer);
        if (targetType.isArray()) {
        if (targetType.isArray()) {
            mAccessor = BracketAccessor.ARRAY;
            mAccessor = BracketAccessor.ARRAY;
        } else if (List.class.isAssignableFrom(targetType)) {
        } else if (List.class.isAssignableFrom(targetType)) {
@@ -68,15 +62,15 @@ public class BracketExpr extends Expr {
    }
    }


    protected String computeUniqueKey() {
    protected String computeUniqueKey() {
        return sUniqueKeyJoiner.join(mTarget.computeUniqueKey(), "$", mArg.computeUniqueKey(), "$");
        return sUniqueKeyJoiner.join(getTarget().computeUniqueKey(), "$", getArg().computeUniqueKey(), "$");
    }
    }


    public Expr getTarget() {
    public Expr getTarget() {
        return mTarget;
        return getChildren().get(0);
    }
    }


    public Expr getArg() {
    public Expr getArg() {
        return mArg;
        return getChildren().get(1);
    }
    }


    public BracketAccessor getAccessor() {
    public BracketAccessor getAccessor() {
@@ -84,6 +78,6 @@ public class BracketExpr extends Expr {
    }
    }


    public boolean argCastsInteger() {
    public boolean argCastsInteger() {
        return Object.class.equals(mArg.getResolvedType());
        return Object.class.equals(getArg().getResolvedType());
    }
    }
}
}
Loading