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

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

Use setTag(id, val) when minSdk is ICS and later.

setTag(id, val) leaks on versions before ICS. When the
minimum SDK is before ICS, setTag(val) must be used
for bindings. However, this prevents the developer from
using the tag for his or her own purposes. Therefore,
if the minimum SDK is ICS and greater, setTag(id, val)
is used.

Change-Id: I46327084bde4bafc05a64f82ad5ebcf710820ecc
parent dfbaf13b
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ public class ProcessExpressions extends ProcessDataBinding.ProcessingStep {
        for (Intermediate intermediate : intermediates) {
            intermediate.appendTo(resourceBundle);
        }
        writeResourceBundle(resourceBundle, buildInfo.isLibrary());
        writeResourceBundle(resourceBundle, buildInfo.isLibrary(), buildInfo.minSdk());
    }

    private IntermediateV1 createIntermediateFromLayouts(String layoutInfoFolderPath) {
@@ -119,14 +119,15 @@ public class ProcessExpressions extends ProcessDataBinding.ProcessingStep {
        return result;
    }

    private void writeResourceBundle(ResourceBundle resourceBundle, boolean forLibraryModule)
    private void writeResourceBundle(ResourceBundle resourceBundle, boolean forLibraryModule,
            int minSdk)
            throws JAXBException {
        CompilerChef compilerChef = CompilerChef.createChef(resourceBundle, getWriter());
        if (compilerChef.hasAnythingToGenerate()) {
            compilerChef.addBRVariables(mProcessBindable);
            compilerChef.writeViewBinderInterfaces(forLibraryModule);
            if (!forLibraryModule) {
                compilerChef.writeDbrFile();
                compilerChef.writeDbrFile(minSdk);
                compilerChef.writeViewBinders();
            }
        }
+2 −2
Original line number Diff line number Diff line
@@ -57,11 +57,11 @@ public class CompilerChef {
        return mResourceBundle != null && mResourceBundle.getLayoutBundles().size() > 0;
    }

    public void writeDbrFile() {
    public void writeDbrFile(int minSdk) {
        ensureDataBinder();
        final String pkg = "android.databinding";
        DataBinderWriter dbr = new DataBinderWriter(pkg, mResourceBundle.getAppPackage(),
                "DataBinderMapper", mDataBinder.getLayoutBinders());
                "DataBinderMapper", mDataBinder.getLayoutBinders(), minSdk);
        if (dbr.getLayoutBinders().size() > 0) {
            mFileWriter.writeToFile(pkg + "." + dbr.getClassName(), dbr.write());
        }
+4 −1
Original line number Diff line number Diff line
@@ -15,7 +15,8 @@ package android.databinding.tool.writer

import android.databinding.tool.LayoutBinder

class DataBinderWriter(val pkg: String, val projectPackage: String, val className: String, val layoutBinders : List<LayoutBinder> ) {
class DataBinderWriter(val pkg: String, val projectPackage: String, val className: String,
        val layoutBinders : List<LayoutBinder>, val minSdk : kotlin.Int) {
    fun write() =
            kcode("") {
                nl("package $pkg;")
@@ -52,6 +53,8 @@ class DataBinderWriter(val pkg: String, val projectPackage: String, val classNam
                    tab("public int getId(String key) {") {
                        tab("return BR.getId(key);")
                    } tab("}")

                    tab("final static int TARGET_MIN_SDK = ${minSdk};")
                }
                nl("}")
            }.generate()
+2 −1
Original line number Diff line number Diff line
@@ -23,11 +23,12 @@ import android.view.View;
 * as part of the code generation step. This class's existence is just to ensure that
 * compile works and no reflection is needed to access the generated class.
 */
public class DataBinderMapper {
class DataBinderMapper {
    public ViewDataBinding getDataBinder(View view, int layoutId) {
        return null;
    }
    public int getId(String key) {
        return 0;
    }
    public static int TARGET_MIN_SDK = 0;
}
+18 −3
Original line number Diff line number Diff line
@@ -16,9 +16,13 @@

package android.databinding;

import com.android.databinding.library.R;

import android.annotation.TargetApi;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.util.Log;
import android.util.SparseIntArray;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
@@ -43,6 +47,9 @@ public abstract class ViewDataBinding {
    // The length of BINDING_TAG_PREFIX prevents calling length repeatedly.
    private static final int BINDING_NUMBER_START = BINDING_TAG_PREFIX.length();

    // ICS (v 14) fixes a leak when using setTag(int, Object)
    private static final boolean USE_TAG_ID = DataBinderMapper.TARGET_MIN_SDK >= 14;

    /**
     * Method object extracted out to attach a listener to a bound Observable object.
     */
@@ -84,7 +91,12 @@ public abstract class ViewDataBinding {
                @Override
                public void onViewAttachedToWindow(View v) {
                    // execute the pending bindings.
                    ViewDataBinding binding = (ViewDataBinding) v.getTag();
                    final ViewDataBinding binding;
                    if (USE_TAG_ID) {
                        binding = (ViewDataBinding) v.getTag(R.id.dataBinding);
                    } else {
                        binding = (ViewDataBinding) v.getTag();
                    }
                    v.post(binding.mRebindRunnable);
                    v.removeOnAttachStateChangeListener(this);
                }
@@ -138,9 +150,12 @@ public abstract class ViewDataBinding {
    protected ViewDataBinding(View root, int localFieldCount) {
        mLocalFieldObservers = new WeakListener[localFieldCount];
        this.mRoot = root;
        // TODO: When targeting ICS and above, use setTag(id, this) instead
        if (USE_TAG_ID) {
            this.mRoot.setTag(R.id.dataBinding, this);
        } else {
            this.mRoot.setTag(this);
        }
    }

    public static int getBuildSdkInt() {
        return SDK_INT;
Loading