13d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar/*
23d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar * Copyright (C) 2014 The Android Open Source Project
33d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar *
43d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
53d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar * you may not use this file except in compliance with the License.
63d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar * You may obtain a copy of the License at
73d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar *
83d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
93d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar *
103d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar * Unless required by applicable law or agreed to in writing, software
113d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
123d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar * See the License for the specific language governing permissions and
143d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar * limitations under the License.
153d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar */
163d4bdfeeb2ffd1b2ec8a26abd1f4306295a66a43Yigit Boyar
17fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding;
18fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount
195914aa7da50a90a4c705b5be02a215499d0ad232George Mountimport android.annotation.TargetApi;
20d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mountimport android.content.res.ColorStateList;
21e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mountimport android.databinding.CallbackRegistry.NotifierCallback;
22d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mountimport android.graphics.drawable.Drawable;
234c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mountimport android.os.Build.VERSION;
244c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mountimport android.os.Build.VERSION_CODES;
253f73e3149732132c02f5d19aab7b5da429794058Yigit Boyarimport android.os.Handler;
263f73e3149732132c02f5d19aab7b5da429794058Yigit Boyarimport android.os.Looper;
2796e1c821dd446d1ed78f8ae61131550588f60a24George Mountimport android.text.TextUtils;
283b920788e90bb0abe615a5d5c899915f0014444bGeorge Mountimport android.util.LongSparseArray;
293b920788e90bb0abe615a5d5c899915f0014444bGeorge Mountimport android.util.SparseArray;
303b920788e90bb0abe615a5d5c899915f0014444bGeorge Mountimport android.util.SparseBooleanArray;
314c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mountimport android.util.SparseIntArray;
323b920788e90bb0abe615a5d5c899915f0014444bGeorge Mountimport android.util.SparseLongArray;
333f73e3149732132c02f5d19aab7b5da429794058Yigit Boyarimport android.view.Choreographer;
34c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mountimport android.view.LayoutInflater;
35085724fd84795ae1631747443c43f77c08e11a28Yigit Boyarimport android.view.View;
365914aa7da50a90a4c705b5be02a215499d0ad232George Mountimport android.view.View.OnAttachStateChangeListener;
3700da715547ee7d5d38a3b8576090ca427a94daa5George Mountimport android.view.ViewGroup;
38085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
393b920788e90bb0abe615a5d5c899915f0014444bGeorge Mountimport com.android.databinding.library.R;
403b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
41085724fd84795ae1631747443c43f77c08e11a28Yigit Boyarimport java.lang.ref.WeakReference;
4276b791f78542a2feb191482a2204de95eaf8ee72George Mountimport java.util.List;
433b920788e90bb0abe615a5d5c899915f0014444bGeorge Mountimport java.util.Map;
44085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
45c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount/**
46c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * Base class for generated data binding classes. If possible, the generated binding should
47c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * be instantiated using one of its generated static bind or inflate methods. If the specific
48c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * binding is unknown, {@link DataBindingUtil#bind(View)} or
49c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * {@link DataBindingUtil#inflate(LayoutInflater, int, ViewGroup, boolean)} should be used.
50c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount */
513b920788e90bb0abe615a5d5c899915f0014444bGeorge Mountpublic abstract class ViewDataBinding extends BaseObservable {
524c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount
534c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
544c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * Instead of directly accessing Build.VERSION.SDK_INT, generated code uses this value so that
554c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * we can test API dependent behavior.
564c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
574c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    static int SDK_INT = VERSION.SDK_INT;
584c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount
59e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    private static final int REBIND = 1;
60e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    private static final int HALTED = 2;
61e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    private static final int REBOUND = 3;
62e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount
634c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
644c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * Prefix for android:tag on Views with binding. The root View and include tags will not have
654c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * android:tag attributes and will use ids instead.
66c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     *
67c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @hide
684c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
697ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount    public static final String BINDING_TAG_PREFIX = "binding_";
704c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount
714c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    // The length of BINDING_TAG_PREFIX prevents calling length repeatedly.
7200da715547ee7d5d38a3b8576090ca427a94daa5George Mount    private static final int BINDING_NUMBER_START = BINDING_TAG_PREFIX.length();
7300da715547ee7d5d38a3b8576090ca427a94daa5George Mount
74e7c2a5e45d7651899790bd347da635875f9c73fbGeorge Mount    // ICS (v 14) fixes a leak when using setTag(int, Object)
75e7c2a5e45d7651899790bd347da635875f9c73fbGeorge Mount    private static final boolean USE_TAG_ID = DataBinderMapper.TARGET_MIN_SDK >= 14;
76e7c2a5e45d7651899790bd347da635875f9c73fbGeorge Mount
773f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar    private static final boolean USE_CHOREOGRAPHER = SDK_INT >= 16;
783f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar
794c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
804c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * Method object extracted out to attach a listener to a bound Observable object.
814c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
825cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {
835cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
844c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
85722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();
865cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
875cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    };
885cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
894c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
904c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * Method object extracted out to attach a listener to a bound ObservableList object.
914c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
925cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    private static final CreateWeakListener CREATE_LIST_LISTENER = new CreateWeakListener() {
935cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
944c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
95722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            return new WeakListListener(viewDataBinding, localFieldId).getListener();
965cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
975cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    };
985cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
994c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
1004c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * Method object extracted out to attach a listener to a bound ObservableMap object.
1014c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
1025cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    private static final CreateWeakListener CREATE_MAP_LISTENER = new CreateWeakListener() {
1035cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
1044c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
105722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            return new WeakMapListener(viewDataBinding, localFieldId).getListener();
1065cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
1075cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    };
1085cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
109e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    private static final CallbackRegistry.NotifierCallback<OnRebindCallback, ViewDataBinding, Void>
110e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        REBIND_NOTIFIER = new NotifierCallback<OnRebindCallback, ViewDataBinding, Void>() {
111e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        @Override
112e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        public void onNotifyCallback(OnRebindCallback callback, ViewDataBinding sender, int mode,
113e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                Void arg2) {
114e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            switch (mode) {
115e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                case REBIND:
116e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                    if (!callback.onPreBind(sender)) {
117e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                        sender.mRebindHalted = true;
118e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                    }
119e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                    break;
120e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                case HALTED:
121e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                    callback.onCanceled(sender);
122e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                    break;
123e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                case REBOUND:
124e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                    callback.onBound(sender);
125e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                    break;
126e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            }
127e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        }
128e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    };
129e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount
1305914aa7da50a90a4c705b5be02a215499d0ad232George Mount    private static final OnAttachStateChangeListener ROOT_REATTACHED_LISTENER;
1315914aa7da50a90a4c705b5be02a215499d0ad232George Mount
1325914aa7da50a90a4c705b5be02a215499d0ad232George Mount    static {
1335914aa7da50a90a4c705b5be02a215499d0ad232George Mount        if (VERSION.SDK_INT < VERSION_CODES.KITKAT) {
1345914aa7da50a90a4c705b5be02a215499d0ad232George Mount            ROOT_REATTACHED_LISTENER = null;
1355914aa7da50a90a4c705b5be02a215499d0ad232George Mount        } else {
1365914aa7da50a90a4c705b5be02a215499d0ad232George Mount            ROOT_REATTACHED_LISTENER = new OnAttachStateChangeListener() {
1375914aa7da50a90a4c705b5be02a215499d0ad232George Mount                @TargetApi(VERSION_CODES.KITKAT)
1385914aa7da50a90a4c705b5be02a215499d0ad232George Mount                @Override
1395914aa7da50a90a4c705b5be02a215499d0ad232George Mount                public void onViewAttachedToWindow(View v) {
1405914aa7da50a90a4c705b5be02a215499d0ad232George Mount                    // execute the pending bindings.
1414d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount                    final ViewDataBinding binding = getBinding(v);
1423f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar                    binding.mRebindRunnable.run();
1435914aa7da50a90a4c705b5be02a215499d0ad232George Mount                    v.removeOnAttachStateChangeListener(this);
1445914aa7da50a90a4c705b5be02a215499d0ad232George Mount                }
1455914aa7da50a90a4c705b5be02a215499d0ad232George Mount
1465914aa7da50a90a4c705b5be02a215499d0ad232George Mount                @Override
1475914aa7da50a90a4c705b5be02a215499d0ad232George Mount                public void onViewDetachedFromWindow(View v) {
1485914aa7da50a90a4c705b5be02a215499d0ad232George Mount                }
1495914aa7da50a90a4c705b5be02a215499d0ad232George Mount            };
1505914aa7da50a90a4c705b5be02a215499d0ad232George Mount        }
1515914aa7da50a90a4c705b5be02a215499d0ad232George Mount    }
1525914aa7da50a90a4c705b5be02a215499d0ad232George Mount
1534c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
1544c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * Runnable executed on animation heartbeat to rebind the dirty Views.
1554c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
1563f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar    private final Runnable mRebindRunnable = new Runnable() {
157085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        @Override
158085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        public void run() {
159e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            synchronized (this) {
160e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                mPendingRebind = false;
161e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            }
162e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
163e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                // Nested so that we don't get a lint warning in IntelliJ
164e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                if (!mRoot.isAttachedToWindow()) {
165e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                    // Don't execute the pending bindings until the View
166e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                    // is attached again.
167e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                    mRoot.removeOnAttachStateChangeListener(ROOT_REATTACHED_LISTENER);
168e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                    mRoot.addOnAttachStateChangeListener(ROOT_REATTACHED_LISTENER);
169e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                    return;
1705914aa7da50a90a4c705b5be02a215499d0ad232George Mount                }
1714c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
172e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            executePendingBindings();
173085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
174085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    };
175085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
1764c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
1774c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * Flag indicates that there are pending bindings that need to be reevaluated.
1784c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
1794c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    private boolean mPendingRebind = false;
1804c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount
1814c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
182e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * Indicates that a onPreBind has stopped the executePendingBindings call.
183e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     */
184e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    private boolean mRebindHalted = false;
185e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount
186e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    /**
1874c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * The observed expressions.
1884c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
1894c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    private WeakListener[] mLocalFieldObservers;
1904c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount
1914c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
1924c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * The root View that this Binding is associated with.
1934c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
1944c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    private final View mRoot;
1954c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount
196e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    /**
197e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * The collection of OnRebindCallbacks.
198e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     */
199e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    private CallbackRegistry<OnRebindCallback, ViewDataBinding, Void> mRebindCallbacks;
200e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount
201e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    /**
202e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * Flag to prevent reentrant executePendingBinding calls.
203e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     */
204e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    private boolean mIsExecutingPendingBindings;
205e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount
2063f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar    // null api < 16
2073f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar    private Choreographer mChoreographer;
2083f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar
2093f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar    private final Choreographer.FrameCallback mFrameCallback;
2103f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar
2113f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar    // null api >= 16
2123f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar    private Handler mUIThreadHandler;
2133f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar
214e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
215e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * The DataBindingComponent used by this data binding. This is used for BindingAdapters
216e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * that are instance methods to retrieve the class instance that implements the
217e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * adapter.
218e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     *
219e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
220e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
221e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    protected final DataBindingComponent mBindingComponent;
222e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount
223e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
224e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
225e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
226e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    protected ViewDataBinding(DataBindingComponent bindingComponent, View root, int localFieldCount) {
227e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        mBindingComponent = bindingComponent;
2285cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        mLocalFieldObservers = new WeakListener[localFieldCount];
2294c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        this.mRoot = root;
2303f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar        if (Looper.myLooper() == null) {
2313f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar            throw new IllegalStateException("DataBinding must be created in view's UI Thread");
2323f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar        }
2333f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar        if (USE_CHOREOGRAPHER) {
2343f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar            mChoreographer = Choreographer.getInstance();
2353f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar            mFrameCallback = new Choreographer.FrameCallback() {
2363f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar                @Override
2373f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar                public void doFrame(long frameTimeNanos) {
2383f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar                    mRebindRunnable.run();
2393f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar                }
2403f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar            };
2413f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar        } else {
2423f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar            mFrameCallback = null;
2433f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar            mUIThreadHandler = new Handler(Looper.myLooper());
2443f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar        }
24596e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
24696e1c821dd446d1ed78f8ae61131550588f60a24George Mount
247e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
248e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
249e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
25096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    protected void setRootTag(View view) {
25196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (USE_TAG_ID) {
25296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            view.setTag(R.id.dataBinding, this);
25396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
25496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            view.setTag(this);
25596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
25696e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
25796e1c821dd446d1ed78f8ae61131550588f60a24George Mount
258e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
259e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
260e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
26196e1c821dd446d1ed78f8ae61131550588f60a24George Mount    protected void setRootTag(View[] views) {
262e7c2a5e45d7651899790bd347da635875f9c73fbGeorge Mount        if (USE_TAG_ID) {
26396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            for (View view : views) {
26496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                view.setTag(R.id.dataBinding, this);
26596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
266e7c2a5e45d7651899790bd347da635875f9c73fbGeorge Mount        } else {
26796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            for (View view : views) {
26896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                view.setTag(this);
26996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
270e7c2a5e45d7651899790bd347da635875f9c73fbGeorge Mount        }
2715cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
2725cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
273e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
274e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
275e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
2764c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    public static int getBuildSdkInt() {
2774c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        return SDK_INT;
2784c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    }
2794c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount
2804c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
2814c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * Called when an observed object changes. Sets the appropriate dirty flag if applicable.
2824c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * @param localFieldId The index into mLocalFieldObservers that this Object resides in.
2834c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * @param object The object that has changed.
284fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount     * @param fieldId The BR ID of the field being changed or _all if
2854c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     *                no specific field is being notified.
2864c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * @return true if this change should cause a change to the UI.
287c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @hide
2884c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
2894c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    protected abstract boolean onFieldChange(int localFieldId, Object object, int fieldId);
2904c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount
291e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    /**
292e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * Set a value value in the Binding class.
293e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * <p>
294e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * Typically, the developer will be able to call the subclass's set method directly. For
295e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * example, if there is a variable <code>x</code> in the Binding, a <code>setX</code> method
296e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * will be generated. However, there are times when the specific subclass of ViewDataBinding
297e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * is unknown, so the generated method cannot be discovered without reflection. The
298e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * setVariable call allows the values of variables to be set without reflection.
299e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     *
300e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * @param variableId the BR id of the variable to be set. For example, if the variable is
301e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     *                   <code>x</code>, then variableId will be <code>BR.x</code>.
302e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * @param value The new value of the variable to be set.
30323910cf498c35704a03ba4f3889de2ab97ccbe21George Mount     * @return <code>true</code> if the variable is declared or used in the binding or
30423910cf498c35704a03ba4f3889de2ab97ccbe21George Mount     * <code>false</code> otherwise.
305e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     */
306e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    public abstract boolean setVariable(int variableId, Object value);
307e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount
308e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    /**
309e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * Add a listener to be called when reevaluating dirty fields. This also allows automatic
310e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * updates to be halted, but does not stop explicit calls to {@link #executePendingBindings()}.
311e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     *
312e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * @param listener The listener to add.
313e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     */
314e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    public void addOnRebindCallback(OnRebindCallback listener) {
315e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        if (mRebindCallbacks == null) {
316e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            mRebindCallbacks = new CallbackRegistry<OnRebindCallback, ViewDataBinding, Void>(REBIND_NOTIFIER);
317e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        }
318e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        mRebindCallbacks.add(listener);
319e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    }
320e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount
321e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    /**
322e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * Removes a listener that was added in {@link #addOnRebindCallback(OnRebindCallback)}.
323e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     *
324e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     * @param listener The listener to remove.
325e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount     */
326e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    public void removeOnRebindCallback(OnRebindCallback listener) {
327e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        if (mRebindCallbacks != null) {
328e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            mRebindCallbacks.remove(listener);
329e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        }
330e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    }
3314c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount
3324c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
3334c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * Evaluates the pending bindings, updating any Views that have expressions bound to
3344c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * modified variables. This <b>must</b> be run on the UI thread.
3354c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
336e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    public void executePendingBindings() {
337e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        if (mIsExecutingPendingBindings) {
338e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            requestRebind();
339e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            return;
340e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        }
341447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        if (!hasPendingBindings()) {
342447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            return;
343447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        }
344e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        mIsExecutingPendingBindings = true;
345e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        mRebindHalted = false;
346e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        if (mRebindCallbacks != null) {
347e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            mRebindCallbacks.notifyCallbacks(this, REBIND, null);
348e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount
349e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            // The onRebindListeners will change mPendingHalted
350e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            if (mRebindHalted) {
351e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                mRebindCallbacks.notifyCallbacks(this, HALTED, null);
352e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            }
353e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        }
354e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        if (!mRebindHalted) {
355e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            executeBindings();
356e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            if (mRebindCallbacks != null) {
357e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                mRebindCallbacks.notifyCallbacks(this, REBOUND, null);
358e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            }
359e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        }
360e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        mIsExecutingPendingBindings = false;
361e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    }
362e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount
363e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    void forceExecuteBindings() {
364e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        executeBindings();
365e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    }
366e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount
367e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
368e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
369e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
370e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount    protected abstract void executeBindings();
3714c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount
3724c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
3732f64c44e4fa296cf658ca986c095eab62f82a31dYigit Boyar     * Invalidates all binding expressions and requests a new rebind to refresh UI.
3744c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
3754c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    public abstract void invalidateAll();
3764c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount
3774c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
3782f64c44e4fa296cf658ca986c095eab62f82a31dYigit Boyar     * Returns whether the UI needs to be refresh to represent the current data.
3792f64c44e4fa296cf658ca986c095eab62f82a31dYigit Boyar     *
380447971abca811b11b8c1d8e7bfaa294856d03c16George Mount     * @return true if any field has changed and the binding should be evaluated.
381447971abca811b11b8c1d8e7bfaa294856d03c16George Mount     */
382447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    public abstract boolean hasPendingBindings();
383447971abca811b11b8c1d8e7bfaa294856d03c16George Mount
384447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    /**
3854c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * Removes binding listeners to expression variables.
3864c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
3874c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    public void unbind() {
3885cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        for (WeakListener weakListener : mLocalFieldObservers) {
3895cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            if (weakListener != null) {
3905cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                weakListener.unregister();
3915cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            }
3925cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
393085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    }
394085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
3954c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    @Override
3964c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    protected void finalize() throws Throwable {
3974c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        unbind();
3984c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    }
3994c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount
400ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount    static ViewDataBinding getBinding(View v) {
4014d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount        if (v != null) {
4024d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount            if (USE_TAG_ID) {
4034d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount                return (ViewDataBinding) v.getTag(R.id.dataBinding);
4044d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount            } else {
4054d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount                final Object tag = v.getTag();
4064d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount                if (tag instanceof ViewDataBinding) {
4074d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount                    return (ViewDataBinding) tag;
4084d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount                }
409ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount            }
410ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount        }
411ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount        return null;
412ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount    }
413ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount
4144c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
415c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * Returns the outermost View in the layout file associated with the Binding. If this
416c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * binding is for a merge layout file, this will return the first root in the merge tag.
417c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     *
4184c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     * @return the outermost View in the layout file associated with the Binding.
4194c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
420085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    public View getRoot() {
421085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        return mRoot;
422085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    }
423085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
424085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
425085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        boolean result = onFieldChange(mLocalFieldId, object, fieldId);
426085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        if (result) {
427085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar            requestRebind();
428085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
429085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    }
430085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
431e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
432e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
433e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
434085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    protected boolean unregisterFrom(int localFieldId) {
4355cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        WeakListener listener = mLocalFieldObservers[localFieldId];
436085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        if (listener != null) {
437085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar            return listener.unregister();
438085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
439085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        return false;
440085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    }
441085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
442e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
443e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
444e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
445085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    protected void requestRebind() {
446e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        synchronized (this) {
447e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            if (mPendingRebind) {
448e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount                return;
449e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            }
450e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount            mPendingRebind = true;
451085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
4523f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar        if (USE_CHOREOGRAPHER) {
4533f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar            mChoreographer.postFrameCallback(mFrameCallback);
4544c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        } else {
4553f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar            mUIThreadHandler.post(mRebindRunnable);
4564c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        }
4573f73e3149732132c02f5d19aab7b5da429794058Yigit Boyar
458085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    }
459085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
460e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
461e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
462e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
463085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    protected Object getObservedField(int localFieldId) {
4645cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        WeakListener listener = mLocalFieldObservers[localFieldId];
465085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        if (listener == null) {
466085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar            return null;
467085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
468085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        return listener.getTarget();
469085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    }
470085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
4715cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    private boolean updateRegistration(int localFieldId, Object observable,
4725cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            CreateWeakListener listenerCreator) {
473085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        if (observable == null) {
474085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar            return unregisterFrom(localFieldId);
475085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
4765cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        WeakListener listener = mLocalFieldObservers[localFieldId];
477085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        if (listener == null) {
4785cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            registerTo(localFieldId, observable, listenerCreator);
479085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar            return true;
480085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
481085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        if (listener.getTarget() == observable) {
482085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar            return false;//nothing to do, same object
483085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
484085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        unregisterFrom(localFieldId);
4855cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        registerTo(localFieldId, observable, listenerCreator);
486085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        return true;
487085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    }
488085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
489e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
490e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
491e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
4925cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    protected boolean updateRegistration(int localFieldId, Observable observable) {
4935cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        return updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER);
4945cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
4955cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
496e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
497e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
498e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
4995cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    protected boolean updateRegistration(int localFieldId, ObservableList observable) {
5005cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        return updateRegistration(localFieldId, observable, CREATE_LIST_LISTENER);
5015cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
5025cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
503e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
504e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
505e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
5065cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    protected boolean updateRegistration(int localFieldId, ObservableMap observable) {
5075cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        return updateRegistration(localFieldId, observable, CREATE_MAP_LISTENER);
5085cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
5095cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
510e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
511e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
512e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
513e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    protected void ensureBindingComponentIsNotNull(Class<?> oneExample) {
514e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        if (mBindingComponent == null) {
515e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            String errorMessage = "Required DataBindingComponent is null in class " +
516e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    getClass().getSimpleName() + ". A BindingAdapter in " +
517e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    oneExample.getCanonicalName() +
518e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    " is not static and requires an object to use, retrieved from the " +
519e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    "DataBindingComponent. If you don't use an inflation method taking a " +
520e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    "DataBindingComponent, use DataBindingUtil.setDefaultComponent or " +
521e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    "make all BindingAdapter methods static.";
522e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            throw new IllegalStateException(errorMessage);
523e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        }
524e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    }
525e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount
526e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
527e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
528e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
5295cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    protected void registerTo(int localFieldId, Object observable,
5305cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            CreateWeakListener listenerCreator) {
531085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        if (observable == null) {
532085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar            return;
533085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
5345cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        WeakListener listener = mLocalFieldObservers[localFieldId];
535085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        if (listener == null) {
5365cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            listener = listenerCreator.create(this, localFieldId);
537085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar            mLocalFieldObservers[localFieldId] = listener;
538085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
539085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        listener.setTarget(observable);
540085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    }
541085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
542e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    /**
543e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
544e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     */
545e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    protected static ViewDataBinding bind(DataBindingComponent bindingComponent, View view,
546e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            int layoutId) {
547e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        return DataBindingUtil.bind(bindingComponent, view, layoutId);
548ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount    }
549ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount
5504c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    /**
55196e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * Walks the view hierarchy under root and pulls out tagged Views, includes, and views with
55296e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * IDs into an Object[] that is returned. This is used to walk the view hierarchy once to find
55396e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * all bound and ID'd views.
55496e1c821dd446d1ed78f8ae61131550588f60a24George Mount     *
555e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @param bindingComponent The binding component to use with this binding.
55696e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * @param root The root of the view hierarchy to walk.
55796e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * @param numBindings The total number of ID'd views, views with expressions, and includes
55896e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * @param includes The include layout information, indexed by their container's index.
55996e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * @param viewsWithIds Indexes of views that don't have tags, but have IDs.
56096e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * @return An array of size numBindings containing all Views in the hierarchy that have IDs
56196e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * (with elements in viewsWithIds), are tagged containing expressions, or the bindings for
56296e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * included layouts.
563c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @hide
56496e1c821dd446d1ed78f8ae61131550588f60a24George Mount     */
565e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    protected static Object[] mapBindings(DataBindingComponent bindingComponent, View root,
566e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            int numBindings, IncludedLayouts includes, SparseIntArray viewsWithIds) {
56796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        Object[] bindings = new Object[numBindings];
568e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        mapBindings(bindingComponent, root, bindings, includes, viewsWithIds, true);
56996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        return bindings;
57096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
57196e1c821dd446d1ed78f8ae61131550588f60a24George Mount
57276b791f78542a2feb191482a2204de95eaf8ee72George Mount    /** @hide */
5733b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected int getColorFromResource(int resourceId) {
5743b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (VERSION.SDK_INT >= VERSION_CODES.M) {
5753b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return getRoot().getContext().getColor(resourceId);
5763b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        } else {
5773b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return getRoot().getResources().getColor(resourceId);
5783b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
5793b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
5803b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
5813b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
582d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount    protected ColorStateList getColorStateListFromResource(int resourceId) {
583d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount        if (VERSION.SDK_INT >= VERSION_CODES.M) {
584d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount            return getRoot().getContext().getColorStateList(resourceId);
585d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount        } else {
586d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount            return getRoot().getResources().getColorStateList(resourceId);
587d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount        }
588d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount    }
589d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount
590d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount    /** @hide */
591d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount    protected Drawable getDrawableFromResource(int resourceId) {
592d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount        if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
593d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount            return getRoot().getContext().getDrawable(resourceId);
594d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount        } else {
595d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount            return getRoot().getResources().getDrawable(resourceId);
596d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount        }
597d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount    }
598d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount
599d0bb3f1e1a94747bb3dd8bd2fee315d8816f0f5dGeorge Mount    /** @hide */
60076b791f78542a2feb191482a2204de95eaf8ee72George Mount    protected static <T> T getFromArray(T[] arr, int index) {
6013b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
60276b791f78542a2feb191482a2204de95eaf8ee72George Mount            return null;
60376b791f78542a2feb191482a2204de95eaf8ee72George Mount        }
60476b791f78542a2feb191482a2204de95eaf8ee72George Mount        return arr[index];
60576b791f78542a2feb191482a2204de95eaf8ee72George Mount    }
60676b791f78542a2feb191482a2204de95eaf8ee72George Mount
60776b791f78542a2feb191482a2204de95eaf8ee72George Mount    /** @hide */
6083b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static <T> void setTo(T[] arr, int index, T value) {
6093b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
6103b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
6113b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
6123b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        arr[index] = value;
6133b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
6143b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
6153b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
61676b791f78542a2feb191482a2204de95eaf8ee72George Mount    protected static boolean getFromArray(boolean[] arr, int index) {
6173b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
61876b791f78542a2feb191482a2204de95eaf8ee72George Mount            return false;
61976b791f78542a2feb191482a2204de95eaf8ee72George Mount        }
62076b791f78542a2feb191482a2204de95eaf8ee72George Mount        return arr[index];
62176b791f78542a2feb191482a2204de95eaf8ee72George Mount    }
62276b791f78542a2feb191482a2204de95eaf8ee72George Mount
62376b791f78542a2feb191482a2204de95eaf8ee72George Mount    /** @hide */
6243b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static void setTo(boolean[] arr, int index, boolean value) {
6253b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
6263b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
6273b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
6283b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        arr[index] = value;
6293b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
6303b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
6313b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
63276b791f78542a2feb191482a2204de95eaf8ee72George Mount    protected static byte getFromArray(byte[] arr, int index) {
6333b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
63476b791f78542a2feb191482a2204de95eaf8ee72George Mount            return 0;
63576b791f78542a2feb191482a2204de95eaf8ee72George Mount        }
63676b791f78542a2feb191482a2204de95eaf8ee72George Mount        return arr[index];
63776b791f78542a2feb191482a2204de95eaf8ee72George Mount    }
63876b791f78542a2feb191482a2204de95eaf8ee72George Mount
63976b791f78542a2feb191482a2204de95eaf8ee72George Mount    /** @hide */
6403b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static void setTo(byte[] arr, int index, byte value) {
6413b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
6423b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
6433b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
6443b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        arr[index] = value;
6453b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
6463b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
6473b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
64876b791f78542a2feb191482a2204de95eaf8ee72George Mount    protected static short getFromArray(short[] arr, int index) {
6493b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
65076b791f78542a2feb191482a2204de95eaf8ee72George Mount            return 0;
65176b791f78542a2feb191482a2204de95eaf8ee72George Mount        }
65276b791f78542a2feb191482a2204de95eaf8ee72George Mount        return arr[index];
65376b791f78542a2feb191482a2204de95eaf8ee72George Mount    }
65476b791f78542a2feb191482a2204de95eaf8ee72George Mount
65576b791f78542a2feb191482a2204de95eaf8ee72George Mount    /** @hide */
6563b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static void setTo(short[] arr, int index, short value) {
6573b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
6583b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
6593b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
6603b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        arr[index] = value;
6613b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
6623b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
6633b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
66476b791f78542a2feb191482a2204de95eaf8ee72George Mount    protected static char getFromArray(char[] arr, int index) {
6653b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
66676b791f78542a2feb191482a2204de95eaf8ee72George Mount            return 0;
66776b791f78542a2feb191482a2204de95eaf8ee72George Mount        }
66876b791f78542a2feb191482a2204de95eaf8ee72George Mount        return arr[index];
66976b791f78542a2feb191482a2204de95eaf8ee72George Mount    }
67076b791f78542a2feb191482a2204de95eaf8ee72George Mount
67176b791f78542a2feb191482a2204de95eaf8ee72George Mount    /** @hide */
6723b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static void setTo(char[] arr, int index, char value) {
6733b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
6743b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
6753b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
6763b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        arr[index] = value;
6773b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
6783b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
6793b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
68076b791f78542a2feb191482a2204de95eaf8ee72George Mount    protected static int getFromArray(int[] arr, int index) {
6813b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
68276b791f78542a2feb191482a2204de95eaf8ee72George Mount            return 0;
68376b791f78542a2feb191482a2204de95eaf8ee72George Mount        }
68476b791f78542a2feb191482a2204de95eaf8ee72George Mount        return arr[index];
68576b791f78542a2feb191482a2204de95eaf8ee72George Mount    }
68676b791f78542a2feb191482a2204de95eaf8ee72George Mount
68776b791f78542a2feb191482a2204de95eaf8ee72George Mount    /** @hide */
6883b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static void setTo(int[] arr, int index, int value) {
6893b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
6903b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
6913b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
6923b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        arr[index] = value;
6933b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
6943b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
6953b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
69676b791f78542a2feb191482a2204de95eaf8ee72George Mount    protected static long getFromArray(long[] arr, int index) {
6973b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
69876b791f78542a2feb191482a2204de95eaf8ee72George Mount            return 0;
69976b791f78542a2feb191482a2204de95eaf8ee72George Mount        }
70076b791f78542a2feb191482a2204de95eaf8ee72George Mount        return arr[index];
70176b791f78542a2feb191482a2204de95eaf8ee72George Mount    }
70276b791f78542a2feb191482a2204de95eaf8ee72George Mount
70376b791f78542a2feb191482a2204de95eaf8ee72George Mount    /** @hide */
7043b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static void setTo(long[] arr, int index, long value) {
7053b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
7063b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
7073b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
7083b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        arr[index] = value;
7093b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
7103b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
7113b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
71276b791f78542a2feb191482a2204de95eaf8ee72George Mount    protected static float getFromArray(float[] arr, int index) {
7133b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
71476b791f78542a2feb191482a2204de95eaf8ee72George Mount            return 0;
71576b791f78542a2feb191482a2204de95eaf8ee72George Mount        }
71676b791f78542a2feb191482a2204de95eaf8ee72George Mount        return arr[index];
71776b791f78542a2feb191482a2204de95eaf8ee72George Mount    }
71876b791f78542a2feb191482a2204de95eaf8ee72George Mount
71976b791f78542a2feb191482a2204de95eaf8ee72George Mount    /** @hide */
7203b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static void setTo(float[] arr, int index, float value) {
7213b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
7223b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
7233b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
7243b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        arr[index] = value;
7253b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
7263b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
7273b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
72876b791f78542a2feb191482a2204de95eaf8ee72George Mount    protected static double getFromArray(double[] arr, int index) {
7293b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
73076b791f78542a2feb191482a2204de95eaf8ee72George Mount            return 0;
73176b791f78542a2feb191482a2204de95eaf8ee72George Mount        }
73276b791f78542a2feb191482a2204de95eaf8ee72George Mount        return arr[index];
73376b791f78542a2feb191482a2204de95eaf8ee72George Mount    }
73476b791f78542a2feb191482a2204de95eaf8ee72George Mount
73576b791f78542a2feb191482a2204de95eaf8ee72George Mount    /** @hide */
7363b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static void setTo(double[] arr, int index, double value) {
7373b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (arr == null || index < 0 || index >= arr.length) {
7383b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
7393b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
7403b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        arr[index] = value;
7413b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
7423b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
7433b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
74476b791f78542a2feb191482a2204de95eaf8ee72George Mount    protected static <T> T getFromList(List<T> list, int index) {
7453b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0 || index >= list.size()) {
7463b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return null;
7473b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
7483b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        return list.get(index);
7493b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
7503b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
7513b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
7523b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static <T> void setTo(List<T> list, int index, T value) {
7533b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0 || index >= list.size()) {
7543b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
7553b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
7563b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        list.set(index, value);
7573b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
7583b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
7593b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
7603b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static <T> T getFromList(SparseArray<T> list, int index) {
7613b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0) {
7623b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return null;
7633b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
7643b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        return list.get(index);
7653b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
7663b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
7673b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
7683b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static <T> void setTo(SparseArray<T> list, int index, T value) {
7693b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0 || index >= list.size()) {
7703b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
7713b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
7723b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        list.put(index, value);
7733b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
7743b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
7753b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
7763b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    @TargetApi(VERSION_CODES.JELLY_BEAN)
7773b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static <T> T getFromList(LongSparseArray<T> list, int index) {
7783b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0) {
77976b791f78542a2feb191482a2204de95eaf8ee72George Mount            return null;
78076b791f78542a2feb191482a2204de95eaf8ee72George Mount        }
78176b791f78542a2feb191482a2204de95eaf8ee72George Mount        return list.get(index);
78276b791f78542a2feb191482a2204de95eaf8ee72George Mount    }
78376b791f78542a2feb191482a2204de95eaf8ee72George Mount
7843b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
7853b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    @TargetApi(VERSION_CODES.JELLY_BEAN)
7863b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static <T> void setTo(LongSparseArray<T> list, int index, T value) {
7873b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0 || index >= list.size()) {
7883b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
7893b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
7903b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        list.put(index, value);
7913b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
7923b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
7933b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
7943b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static <T> T getFromList(android.support.v4.util.LongSparseArray<T> list, int index) {
7953b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0) {
7963b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return null;
7973b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
7983b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        return list.get(index);
7993b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
8003b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
8013b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
8023b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static <T> void setTo(android.support.v4.util.LongSparseArray<T> list, int index,
8033b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            T value) {
8043b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0 || index >= list.size()) {
8053b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
8063b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
8073b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        list.put(index, value);
8083b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
8093b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
8103b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
8113b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static boolean getFromList(SparseBooleanArray list, int index) {
8123b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0) {
8133b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return false;
8143b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
8153b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        return list.get(index);
8163b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
8173b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
8183b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
8193b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static void setTo(SparseBooleanArray list, int index, boolean value) {
8203b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0 || index >= list.size()) {
8213b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
8223b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
8233b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        list.put(index, value);
8243b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
8253b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
8263b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
8273b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static int getFromList(SparseIntArray list, int index) {
8283b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0) {
8293b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return 0;
8303b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
8313b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        return list.get(index);
8323b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
8333b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
8343b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
8353b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static void setTo(SparseIntArray list, int index, int value) {
8363b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0 || index >= list.size()) {
8373b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
8383b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
8393b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        list.put(index, value);
8403b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
8413b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
8423b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
8433b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    @TargetApi(VERSION_CODES.JELLY_BEAN_MR2)
8443b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static long getFromList(SparseLongArray list, int index) {
8453b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0) {
8463b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return 0;
8473b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
8483b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        return list.get(index);
8493b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
8503b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
8513b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
8523b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    @TargetApi(VERSION_CODES.JELLY_BEAN_MR2)
8533b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static void setTo(SparseLongArray list, int index, long value) {
8543b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (list == null || index < 0 || index >= list.size()) {
8553b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
8563b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
8573b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        list.put(index, value);
8583b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
8593b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
8603b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
8613b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static <K, T> T getFrom(Map<K, T> map, K key) {
8623b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (map == null) {
8633b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return null;
8643b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
8653b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        return map.get(key);
8663b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
8673b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
8683b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
8693b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static <K, T> void setTo(Map<K, T> map, K key, T value) {
8703b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (map == null) {
8713b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            return;
8723b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
8733b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        map.put(key, value);
8743b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
8753b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
8763b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /** @hide */
8773b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static void setBindingInverseListener(ViewDataBinding binder,
8783b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            InverseBindingListener oldListener, PropertyChangedInverseListener listener) {
8793b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        if (oldListener != listener) {
8803b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            if (oldListener != null) {
8813b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount                binder.removeOnPropertyChangedCallback(
8823b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount                        (PropertyChangedInverseListener) oldListener);
8833b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            }
8843b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            if (listener != null) {
8853b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount                binder.addOnPropertyChangedCallback(listener);
8863b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            }
8873b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
8883b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
8893b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
89096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    /**
89196e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * Walks the view hierarchy under roots and pulls out tagged Views, includes, and views with
89296e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * IDs into an Object[] that is returned. This is used to walk the view hierarchy once to find
89396e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * all bound and ID'd views.
8944c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     *
895e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @param bindingComponent The binding component to use with this binding.
89696e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * @param roots The root Views of the view hierarchy to walk. This is used with merge tags.
89796e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * @param numBindings The total number of ID'd views, views with expressions, and includes
89896e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * @param includes The include layout information, indexed by their container's index.
89996e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * @param viewsWithIds Indexes of views that don't have tags, but have IDs.
90096e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * @return An array of size numBindings containing all Views in the hierarchy that have IDs
90196e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * (with elements in viewsWithIds), are tagged containing expressions, or the bindings for
90296e1c821dd446d1ed78f8ae61131550588f60a24George Mount     * included layouts.
903e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount     * @hide
9044c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount     */
905e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    protected static Object[] mapBindings(DataBindingComponent bindingComponent, View[] roots,
906e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            int numBindings, IncludedLayouts includes, SparseIntArray viewsWithIds) {
90796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        Object[] bindings = new Object[numBindings];
90896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        for (int i = 0; i < roots.length; i++) {
909e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            mapBindings(bindingComponent, roots[i], bindings, includes, viewsWithIds, true);
91000da715547ee7d5d38a3b8576090ca427a94daa5George Mount        }
91196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        return bindings;
91200da715547ee7d5d38a3b8576090ca427a94daa5George Mount    }
91300da715547ee7d5d38a3b8576090ca427a94daa5George Mount
914e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    private static void mapBindings(DataBindingComponent bindingComponent, View view,
915e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            Object[] bindings, IncludedLayouts includes, SparseIntArray viewsWithIds,
916e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            boolean isRoot) {
917239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        final int indexInIncludes;
918d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount        final ViewDataBinding existingBinding = getBinding(view);
919d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount        if (existingBinding != null) {
9204d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount            return;
9214d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount        }
92296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        final String tag = (String) view.getTag();
92396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        boolean isBound = false;
92496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (isRoot && tag != null && tag.startsWith("layout")) {
92596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            final int underscoreIndex = tag.lastIndexOf('_');
92696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            if (underscoreIndex > 0 && isNumeric(tag, underscoreIndex + 1)) {
92796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                final int index = parseTagInt(tag, underscoreIndex + 1);
928716ba89e7f459f49ea85070d4710c1d79d715298George Mount                if (bindings[index] == null) {
929716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    bindings[index] = view;
930716ba89e7f459f49ea85070d4710c1d79d715298George Mount                }
931239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                indexInIncludes = includes == null ? -1 : index;
93296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                isBound = true;
93396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            } else {
934239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                indexInIncludes = -1;
93596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
93696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else if (tag != null && tag.startsWith(BINDING_TAG_PREFIX)) {
93796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            int tagIndex = parseTagInt(tag, BINDING_NUMBER_START);
938716ba89e7f459f49ea85070d4710c1d79d715298George Mount            if (bindings[tagIndex] == null) {
939716ba89e7f459f49ea85070d4710c1d79d715298George Mount                bindings[tagIndex] = view;
940716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
94196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            isBound = true;
942239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount            indexInIncludes = includes == null ? -1 : tagIndex;
94395d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount        } else {
94496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            // Not a bound view
945239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount            indexInIncludes = -1;
94696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
94796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (!isBound) {
94896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            final int id = view.getId();
94996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            if (id > 0) {
95096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                int index;
951716ba89e7f459f49ea85070d4710c1d79d715298George Mount                if (viewsWithIds != null && (index = viewsWithIds.get(id, -1)) >= 0 &&
952716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        bindings[index] == null) {
95396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    bindings[index] = view;
95496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
95596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
95696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
95796e1c821dd446d1ed78f8ae61131550588f60a24George Mount
95896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (view instanceof  ViewGroup) {
95996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            final ViewGroup viewGroup = (ViewGroup) view;
96096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            final int count = viewGroup.getChildCount();
96196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            int minInclude = 0;
96296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            for (int i = 0; i < count; i++) {
96396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                final View child = viewGroup.getChildAt(i);
96496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                boolean isInclude = false;
965239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                if (indexInIncludes >= 0) {
96696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    String childTag = (String) child.getTag();
96796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (childTag != null && childTag.endsWith("_0") &&
96896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            childTag.startsWith("layout") && childTag.indexOf('/') > 0) {
96996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        // This *could* be an include. Test against the expected includes.
97096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        int includeIndex = findIncludeIndex(childTag, minInclude,
971239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                                includes, indexInIncludes);
97296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        if (includeIndex >= 0) {
97396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            isInclude = true;
97496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            minInclude = includeIndex + 1;
975239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                            final int index = includes.indexes[indexInIncludes][includeIndex];
976239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                            final int layoutId = includes.layoutIds[indexInIncludes][includeIndex];
97796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            int lastMatchingIndex = findLastMatching(viewGroup, i);
97896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            if (lastMatchingIndex == i) {
979e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                                bindings[index] = DataBindingUtil.bind(bindingComponent, child,
980e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                                        layoutId);
98196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            } else {
98296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                                final int includeCount =  lastMatchingIndex - i + 1;
98396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                                final View[] included = new View[includeCount];
98496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                                for (int j = 0; j < includeCount; j++) {
98596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                                    included[j] = viewGroup.getChildAt(i + j);
98696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                                }
987e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                                bindings[index] = DataBindingUtil.bind(bindingComponent, included,
988e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                                        layoutId);
98996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                                i += includeCount - 1;
99096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            }
99196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        }
99296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
99396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
99496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                if (!isInclude) {
995e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    mapBindings(bindingComponent, child, bindings, includes, viewsWithIds, false);
99696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
99796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
9984c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        }
99996e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
100096e1c821dd446d1ed78f8ae61131550588f60a24George Mount
100196e1c821dd446d1ed78f8ae61131550588f60a24George Mount    private static int findIncludeIndex(String tag, int minInclude,
1002239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount            IncludedLayouts included, int includedIndex) {
100396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        final int slashIndex = tag.indexOf('/');
100496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        final CharSequence layoutName = tag.subSequence(slashIndex + 1, tag.length() - 2);
100596e1c821dd446d1ed78f8ae61131550588f60a24George Mount
1006239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        final String[] layouts = included.layouts[includedIndex];
1007239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        final int length = layouts.length;
100896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        for (int i = minInclude; i < length; i++) {
1009239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount            final String layout = layouts[i];
1010239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount            if (TextUtils.equals(layoutName, layout)) {
101196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                return i;
101296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
101300da715547ee7d5d38a3b8576090ca427a94daa5George Mount        }
101496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        return -1;
101500da715547ee7d5d38a3b8576090ca427a94daa5George Mount    }
101600da715547ee7d5d38a3b8576090ca427a94daa5George Mount
101796e1c821dd446d1ed78f8ae61131550588f60a24George Mount    private static int findLastMatching(ViewGroup viewGroup, int firstIncludedIndex) {
101896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        final View firstView = viewGroup.getChildAt(firstIncludedIndex);
101996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        final String firstViewTag = (String) firstView.getTag();
102096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        final String tagBase = firstViewTag.substring(0, firstViewTag.length() - 1); // don't include the "0"
102196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        final int tagSequenceIndex = tagBase.length();
102296e1c821dd446d1ed78f8ae61131550588f60a24George Mount
102396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        final int count = viewGroup.getChildCount();
102496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        int max = firstIncludedIndex;
102596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        for (int i = firstIncludedIndex + 1; i < count; i++) {
102696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            final View view = viewGroup.getChildAt(i);
102796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            final String tag = (String) view.getTag();
102896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            if (tag != null && tag.startsWith(tagBase)) {
102996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                if (tag.length() == firstViewTag.length() && tag.charAt(tag.length() - 1) == '0') {
103096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    return max; // Found another instance of the include
103196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
103296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                if (isNumeric(tag, tagSequenceIndex)) {
103396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    max = i;
103496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
103596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
103696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
103796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        return max;
103834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
103934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount
104096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    private static boolean isNumeric(String tag, int startIndex) {
104196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        int length = tag.length();
104296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (length == startIndex) {
104396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return false; // no numerals
104496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
104596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        for (int i = startIndex; i < length; i++) {
104696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            if (!Character.isDigit(tag.charAt(i))) {
104796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                return false;
104895d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount            }
104995d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount        }
105096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        return true;
105195d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount    }
105295d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount
105334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    /**
105400da715547ee7d5d38a3b8576090ca427a94daa5George Mount     * Parse the tag without creating a new String object. This is fast and assumes the
105500da715547ee7d5d38a3b8576090ca427a94daa5George Mount     * tag is in the correct format.
105600da715547ee7d5d38a3b8576090ca427a94daa5George Mount     * @param str The tag string.
105700da715547ee7d5d38a3b8576090ca427a94daa5George Mount     * @return The binding tag number parsed from the tag string.
105800da715547ee7d5d38a3b8576090ca427a94daa5George Mount     */
105996e1c821dd446d1ed78f8ae61131550588f60a24George Mount    private static int parseTagInt(String str, int startIndex) {
106000da715547ee7d5d38a3b8576090ca427a94daa5George Mount        final int end = str.length();
106100da715547ee7d5d38a3b8576090ca427a94daa5George Mount        int val = 0;
106296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        for (int i = startIndex; i < end; i++) {
106300da715547ee7d5d38a3b8576090ca427a94daa5George Mount            val *= 10;
106400da715547ee7d5d38a3b8576090ca427a94daa5George Mount            char c = str.charAt(i);
106500da715547ee7d5d38a3b8576090ca427a94daa5George Mount            val += (c - '0');
106600da715547ee7d5d38a3b8576090ca427a94daa5George Mount        }
106700da715547ee7d5d38a3b8576090ca427a94daa5George Mount        return val;
106800da715547ee7d5d38a3b8576090ca427a94daa5George Mount    }
106900da715547ee7d5d38a3b8576090ca427a94daa5George Mount
1070722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount    private interface ObservableReference<T> {
1071722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        WeakListener<T> getListener();
1072722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        void addListener(T target);
1073722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        void removeListener(T target);
1074722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount    }
1075722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount
1076722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount    private static class WeakListener<T> extends WeakReference<ViewDataBinding> {
1077722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        private final ObservableReference<T> mObservable;
10785cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        protected final int mLocalFieldId;
10795cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        private T mTarget;
1080085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
1081722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public WeakListener(ViewDataBinding binder, int localFieldId,
1082722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                ObservableReference<T> observable) {
1083722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            super(binder);
10845cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            mLocalFieldId = localFieldId;
1085722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            mObservable = observable;
1086085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
1087085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
10885cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        public void setTarget(T object) {
10895cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            unregister();
10905cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            mTarget = object;
10915cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            if (mTarget != null) {
1092722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                mObservable.addListener(mTarget);
1093085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar            }
1094085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
1095085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
1096085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        public boolean unregister() {
10975cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            boolean unregistered = false;
10985cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            if (mTarget != null) {
1099722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                mObservable.removeListener(mTarget);
11005cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                unregistered = true;
1101085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar            }
1102085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar            mTarget = null;
11035cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            return unregistered;
1104085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
1105085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
11065cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        public T getTarget() {
11075cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            return mTarget;
1108085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
11095cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
11104c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        protected ViewDataBinding getBinder() {
1111722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            ViewDataBinding binder = get();
11125cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            if (binder == null) {
11135cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                unregister(); // The binder is dead
11145cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            }
11155cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            return binder;
11165cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
1117085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    }
1118085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
1119722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount    private static class WeakPropertyListener extends Observable.OnPropertyChangedCallback
1120722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            implements ObservableReference<Observable> {
1121722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        final WeakListener<Observable> mListener;
1122722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount
11234c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        public WeakPropertyListener(ViewDataBinding binder, int localFieldId) {
1124722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            mListener = new WeakListener<Observable>(binder, localFieldId, this);
11255cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
11265cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
11275cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
1128722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public WeakListener<Observable> getListener() {
1129722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            return mListener;
11305cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
11315cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
11325cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
1133722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void addListener(Observable target) {
1134722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            target.addOnPropertyChangedCallback(this);
1135085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
1136085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar
1137085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        @Override
1138722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void removeListener(Observable target) {
1139722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            target.removeOnPropertyChangedCallback(this);
1140722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        }
1141722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount
1142722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        @Override
1143722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void onPropertyChanged(Observable sender, int propertyId) {
1144722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            ViewDataBinding binder = mListener.getBinder();
11455cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            if (binder == null) {
11465cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                return;
11475cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            }
1148722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            Observable obj = mListener.getTarget();
11495cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            if (obj != sender) {
11505cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                return; // notification from the wrong object?
1151085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar            }
1152722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
1153085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar        }
1154085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar    }
11555cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
1156722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount    private static class WeakListListener extends ObservableList.OnListChangedCallback
1157722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            implements ObservableReference<ObservableList> {
1158722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        final WeakListener<ObservableList> mListener;
11595cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
11604c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        public WeakListListener(ViewDataBinding binder, int localFieldId) {
1161722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            mListener = new WeakListener<ObservableList>(binder, localFieldId, this);
11625cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
11635cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
11645cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
1165722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public WeakListener<ObservableList> getListener() {
1166722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            return mListener;
11675cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
11685cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
11695cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
1170722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void addListener(ObservableList target) {
1171722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            target.addOnListChangedCallback(this);
11725cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
11735cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
11745cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
1175722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void removeListener(ObservableList target) {
1176722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            target.removeOnListChangedCallback(this);
11775cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
11785cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
11795cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
1180722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void onChanged(ObservableList sender) {
1181722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            ViewDataBinding binder = mListener.getBinder();
1182722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            if (binder == null) {
1183722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                return;
1184722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            }
1185722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            ObservableList target = mListener.getTarget();
1186722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            if (target != sender) {
1187722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                return; // We expect notifications only from sender
1188722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            }
1189722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            binder.handleFieldChange(mListener.mLocalFieldId, target, 0);
11905cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
11915cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
11925cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
1193722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void onItemRangeChanged(ObservableList sender, int positionStart, int itemCount) {
1194722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            onChanged(sender);
11955cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
11965cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
11975cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
1198722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void onItemRangeInserted(ObservableList sender, int positionStart, int itemCount) {
1199722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            onChanged(sender);
12005cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
12015cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
12025cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
1203722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void onItemRangeMoved(ObservableList sender, int fromPosition, int toPosition,
1204722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                int itemCount) {
1205722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            onChanged(sender);
1206722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        }
1207722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount
1208722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        @Override
1209722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void onItemRangeRemoved(ObservableList sender, int positionStart, int itemCount) {
1210722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            onChanged(sender);
12115cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
12125cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
12135cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
1214722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount    private static class WeakMapListener extends ObservableMap.OnMapChangedCallback
1215722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            implements ObservableReference<ObservableMap> {
1216722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        final WeakListener<ObservableMap> mListener;
1217722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount
12184c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        public WeakMapListener(ViewDataBinding binder, int localFieldId) {
1219722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            mListener = new WeakListener<ObservableMap>(binder, localFieldId, this);
1220722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        }
1221722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount
1222722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        @Override
1223722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public WeakListener<ObservableMap> getListener() {
1224722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            return mListener;
12255cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
12265cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
12275cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
1228722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void addListener(ObservableMap target) {
1229722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            target.addOnMapChangedCallback(this);
12305cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
12315cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
12325cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
1233722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void removeListener(ObservableMap target) {
1234722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            target.removeOnMapChangedCallback(this);
12355cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
12365cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
12375cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
12382c86cdbaf189e2b1774af7f64a2974de9321673fGeorge Mount        public void onMapChanged(ObservableMap sender, Object key) {
1239722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            ViewDataBinding binder = mListener.getBinder();
1240722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            if (binder == null || sender != mListener.getTarget()) {
12415cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                return;
12425cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            }
1243722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            binder.handleFieldChange(mListener.mLocalFieldId, sender, 0);
12445cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
12455cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
12465cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
12475cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    private interface CreateWeakListener {
12484c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        WeakListener create(ViewDataBinding viewDataBinding, int localFieldId);
12495cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
125096e1c821dd446d1ed78f8ae61131550588f60a24George Mount
1251239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount    /**
1252239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount     * This class is used by generated subclasses of {@link ViewDataBinding} to track the
1253239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount     * included layouts contained in the bound layout. This class is an implementation
1254239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount     * detail of how binding expressions are mapped to Views after inflation.
1255239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount     * @hide
1256239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount     */
1257239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount    protected static class IncludedLayouts {
1258239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        public final String[][] layouts;
1259239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        public final int[][] indexes;
1260239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        public final int[][] layoutIds;
1261239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount
1262239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        public IncludedLayouts(int bindingCount) {
1263239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount            layouts = new String[bindingCount][];
1264239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount            indexes = new int[bindingCount][];
1265239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount            layoutIds = new int[bindingCount][];
1266239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        }
126796e1c821dd446d1ed78f8ae61131550588f60a24George Mount
1268239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        public void setIncludes(int index, String[] layouts, int[] indexes, int[] layoutIds) {
1269239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount            this.layouts[index] = layouts;
1270239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount            this.indexes[index] = indexes;
1271239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount            this.layoutIds[index] = layoutIds;
127296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
127396e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
12743b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
12753b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    /**
12763b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount     * This class is used by generated subclasses of {@link ViewDataBinding} to listen for
12773b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount     * changes on variables of Bindings. This is important for two-way data binding on variables
12783b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount     * in included Bindings.
12793b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount     * @hide
12803b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount     */
12813b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    protected static abstract class PropertyChangedInverseListener
12823b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            extends Observable.OnPropertyChangedCallback implements InverseBindingListener {
12833b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        final int mPropertyId;
12843b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
12853b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        public PropertyChangedInverseListener(int propertyId) {
12863b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            mPropertyId = propertyId;
12873b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
12883b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount
12893b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        @Override
12903b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        public void onPropertyChanged(Observable sender, int propertyId) {
12913b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            if (propertyId == mPropertyId || propertyId == 0) {
12923b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount                onChange();
12933b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount            }
12943b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount        }
12953b920788e90bb0abe615a5d5c899915f0014444bGeorge Mount    }
1296085724fd84795ae1631747443c43f77c08e11a28Yigit Boyar}
1297