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