package com.example.viewmodellearn;
import android.os.Build;
import android.text.TextUtils;
import android.util.SparseIntArray;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.databinding.Bindable;
import androidx.databinding.CallbackRegistry;
import androidx.databinding.CreateWeakListener;
import androidx.databinding.DataBindingComponent;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.Observable;
import androidx.databinding.ObservableList;
import androidx.databinding.ObservableMap;
import androidx.databinding.OnRebindCallback;
import androidx.databinding.ViewDataBinding;
import androidx.databinding.WeakListener;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class DataBindingLearn {
/////////////
? ? //注冊流程////
/////////////
? ? /**
? ? * 1.Listerner創(chuàng)建工廠
? ? *? a.只有一個構造函數(shù)可看WeakListener create(ViewDataBinding viewDataBinding,int localFieldId,ReferenceQueue<ViewDataBinding> referenceQueue);
? ? *? ? ? a1.具體對應的ViewDatabinding類
? ? *? ? ? a2.具體fileid
? ? *? ? ? a3.防止內(nèi)存泄漏,里面維護了一套弱引用,這里是弱引用使用的引用隊列
? ? * */
? ? @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
interface CreateWeakListener {
WeakListener create(
ViewDataBinding viewDataBinding,
? ? ? ? ? ? ? ? int localFieldId,
? ? ? ? ? ? ? ? ReferenceQueue referenceQueue);
? ? }
/**
? ? * 2.weakListener 弱引用的封裝類
? ? *? a.看構造函數(shù) public WeakListener(ViewDataBinding binder,int localFieldId,ObservableReference<T> observable,ReferenceQueue<ViewDataBinding> referenceQueue)
? ? *? ? ? a1.binder :? ? ? ? 要保留的binding對象
? ? *? ? ? a2.fileId :
? ? *? ? ? a3.observable:? ? 注冊工具類,用來怎么綁定數(shù)據(jù),定義了常規(guī)的添加,移除監(jiān)聽,添加生命周期,添加
? ? *? ? ? a4.referenceQueue: 引用隊列,防止viewdataBinding泄漏
? ? *? b.局部變量:
? ? *? ? ? b1.ObservableReference<T> mObservable : 注冊工具類
? ? *? ? ? b2.T mTarget? ? ? ? ? ? ? ? ? ? ? ? ? : 發(fā)生改變的數(shù)據(jù)
? ? *? c.特殊說明: T mTarget? 這里,不是具體的觀察者,這里實際應該是 source. 是要觀察的對象
? ? * */
? ? @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
class WeakListenerextends WeakReference {
private final ObservableReference mObservable;
? ? ? ? protected final int mLocalFieldId;
? ? ? ? private T mTarget;
? ? ? ? public WeakListener(
ViewDataBinding binder,
? ? ? ? ? ? ? ? int localFieldId,
? ? ? ? ? ? ? ? ObservableReference observable,
? ? ? ? ? ? ? ? ReferenceQueue referenceQueue
) {
super(binder, referenceQueue);
? ? ? ? ? ? mLocalFieldId = localFieldId;
? ? ? ? ? ? mObservable = observable;
? ? ? ? }
public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
mObservable.setLifecycleOwner(lifecycleOwner);
? ? ? ? }
public void setTarget(T object) {
unregister();
? ? ? ? ? ? mTarget = object;
? ? ? ? ? ? if (mTarget !=null) {
mObservable.addListener(mTarget);
? ? ? ? ? ? }
}
public boolean unregister() {
boolean unregistered =false;
? ? ? ? ? ? if (mTarget !=null) {
mObservable.removeListener(mTarget);
? ? ? ? ? ? ? ? unregistered =true;
? ? ? ? ? ? }
mTarget =null;
? ? ? ? ? ? return unregistered;
? ? ? ? }
public T getTarget() {
return mTarget;
? ? ? ? }
@Nullable
protected ViewDataBinding getBinder() {
ViewDataBinding binder = get();
? ? ? ? ? ? if (binder ==null) {
unregister(); // The binder is dead
? ? ? ? ? ? }
return binder;
? ? ? ? }
}
/**
? ? * 3.ObservableReference 注冊工具類,
? ? *? 用來怎么綁定數(shù)據(jù),定義了常規(guī)的添加,移除監(jiān)聽,添加生命周期,添加
? ? *? addListener(target)這里參考一段兒代碼:WeakPropertyListener 里面的綁定流程是以下
? ? *? ? ? target.addOnPropertyChangedCallback(this);
* */
? ? @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
interface ObservableReference {
androidx.databinding.WeakListener getListener();
? ? ? ? void addListener(T target);
? ? ? ? void removeListener(T target);
? ? ? ? void setLifecycleOwner(LifecycleOwner lifecycleOwner);
? ? }
/**
? ? * 4.系統(tǒng)中使用的注冊類WeakPropertyListener
? ? *? a.繼承了OnPropertyChangedCallback.統(tǒng)一規(guī)定了filechange以后怎么處理
? ? *? b.實現(xiàn)了ObservableReference .定義了怎么進行回調(diào)的綁定
? ? * */
? ? private static class WeakPropertyListenerextends androidx.databinding.Observable.OnPropertyChangedCallback
implements androidx.databinding.ObservableReference {
final androidx.databinding.WeakListener mListener;
? ? ? ? public WeakPropertyListener(
ViewDataBinding binder,
? ? ? ? ? ? ? ? int localFieldId,
? ? ? ? ? ? ? ? ReferenceQueue referenceQueue
) {
mListener =new androidx.databinding.WeakListener(binder, localFieldId, this, referenceQueue);
? ? ? ? }
@Override
public androidx.databinding.WeakListener getListener() {
return mListener;
? ? ? ? }
@Override
public void addLizstener(androidx.databinding.Observable target) {
target.addOnPropertyChangedCallback(this);
? ? ? ? }
@Override
public void removeListener(androidx.databinding.Observable target) {
target.removeOnPropertyChangedCallback(this);
? ? ? ? }
@Override
public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
}
@Override
public void onPropertyChanged(androidx.databinding.Observable sender, int propertyId) {
ViewDataBinding binder = mListener.getBinder();
? ? ? ? ? ? if (binder ==null) {
return;
? ? ? ? ? ? }
androidx.databinding.Observable obj = mListener.getTarget();
? ? ? ? ? ? if (obj != sender) {
return; // notification from the wrong object?
? ? ? ? ? ? }
binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
? ? ? ? }
}
/**
? ? * 5.MainActivityBindingImpl具體的注冊流程
? ? *? setUser()時,先進行綁定注冊
? ? *? ? a.updateRegistration(0, User);
? ? *? ? b.updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER);? 其中CREATE_PROPERTY_LISTENER:就是對應的創(chuàng)建工廠
? ? *? ? ? b1.細節(jié)部分有對 listener的一個緩存
? ? *? ? ? b2.設定lifecycleOwner對象
? ? *? ? ? b3.對listener進行綁定數(shù)據(jù)來源? 即這里的user
* */
? ? protected void registerTo(int localFieldId, Object observable,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? androidx.databinding.CreateWeakListener listenerCreator) {
if (observable ==null) {
return;
? ? ? ? }
androidx.databinding.WeakListener listener = mLocalFieldObservers[localFieldId];
? ? ? ? if (listener ==null) {
listener = listenerCreator.create(this, localFieldId, sReferenceQueue);
? ? ? ? ? ? mLocalFieldObservers[localFieldId] = listener;
? ? ? ? ? ? if (mLifecycleOwner !=null) {
listener.setLifecycleOwner(mLifecycleOwner);
? ? ? ? ? ? }
}
listener.setTarget(observable);
? ? }
//? ? ? ? public void setTarget(T object) {
//? ? ? ? ? ? unregister();
//? ? ? ? ? ? mTarget = object;
//? ? ? ? ? ? if (mTarget != null) {
//? ? ? ? ? ? ? ? mObservable.addListener(mTarget);
//? ? ? ? ? ? }
//? ? ? ? }
? ? ? ? // 然后走對應工具類的addListener
//? ? ? ? @Override
//? ? ? ? public void addLizstener(androidx.databinding.Observable target) {
//? ? ? ? ? ? tgaret.addOnPropertyChangedCallback(this);
//? ? ? ? }
? ? ? ? //此時,完成了user添加OnPropertychangedCallback轉化
? ? ? ? //最終走到WeakListener中
//? ? ? ? @Override
//? ? ? ? public void onPropertyChanged(androidx.databinding.Observable sender, int propertyId) {
//? ? ? ? ? ? ViewDataBinding binder = mListener.getBinder();
//? ? ? ? ? ? if (binder == null) {
//? ? ? ? ? ? ? ? return;
//? ? ? ? ? ? }
//? ? ? ? ? ? androidx.databinding.Observable obj = mListener.getTarget();
//? ? ? ? ? ? if (obj != sender) {
//? ? ? ? ? ? ? ? return; // notification from the wrong object?
//? ? ? ? ? ? }
//? ? ? ? ? ? binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
//? ? ? ? }
? ? ? ? // binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId); 每一個生成的dataBinding對象都實現(xiàn)該方法
? ? @Override
protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
switch (localFieldId) {
case 0 :
return onChangeUser((com.example.viewmodellearn.bean.User) object, fieldId);
? ? ? ? ? ? case 1 :
return onChangeUserName((androidx.databinding.ObservableField) object, fieldId);
? ? ? ? ? ? case 2 :
return onChangeList((androidx.databinding.ObservableArrayList) object, fieldId);
? ? ? ? }
return false;
? ? }
private boolean onChangeUser(com.example.viewmodellearn.bean.User User, int fieldId) {
if (fieldId == BR._all) {
synchronized (this) {
mDirtyFlags |=0x1L;
? ? ? ? ? ? }
return true;
? ? ? ? }else if (fieldId == BR.age) {
synchronized (this) {
mDirtyFlags |=0x20L;
? ? ? ? ? ? }
return true;
? ? ? ? }
return false;
? ? }
// 更改完mDirtyFlags以后. 在requestbind()方法中,會根據(jù)具體的值,進行變量的更改和賦值變化
? ? // requestBind調(diào)用時機 等待進一步完善
? ? // 然后雙向綁定的分析InverseBindingListener
? ? @Override
protected void executeBindings() {
long dirtyFlags =0;
? ? ? ? synchronized(this) {
dirtyFlags = mDirtyFlags;
? ? ? ? ? ? mDirtyFlags =0;
? ? ? ? }
int userAge =0;
? ? ? ? com.example.viewmodellearn.bean.User user = mUser;
? ? ? ? String stringValueOfUserAge =null;
? ? ? ? androidx.databinding.ObservableField userName =null;
? ? ? ? ClickHandlers mainActivity = mMainActivity;
? ? ? ? String userNameGet =null;
? ? ? ? if ((dirtyFlags &0x63L) !=0) {
if ((dirtyFlags &0x61L) !=0) {
if (user !=null) {
// read user.age
? ? ? ? ? ? ? ? ? ? userAge = user.getAge();
? ? ? ? ? ? ? ? }
// read String.valueOf(user.age)
? ? ? ? ? ? ? ? stringValueOfUserAge = String.valueOf(userAge);
? ? ? ? ? ? }
if ((dirtyFlags &0x43L) !=0) {
if (user !=null) {
// read user.name
? ? ? ? ? ? ? ? ? ? userName = user.getName();
? ? ? ? ? ? ? ? }
updateRegistration(1, userName);
? ? ? ? ? ? ? ? if (userName !=null) {
// read user.name.get()
? ? ? ? ? ? ? ? ? ? userNameGet = userName.get();
? ? ? ? ? ? ? ? }
}
}
// batch finished
? ? ? ? if ((dirtyFlags &0x40L) !=0) {
// api target 1
? ? ? ? ? ? this.btnChange.setOnClickListener(mCallback1);
? ? ? ? }
if ((dirtyFlags &0x43L) !=0) {
// api target 1
? ? ? ? ? ? com.example.viewmodellearn.databingding.mainActivityBindAdapter.loadImageFormUrl(this.iv, userNameGet);
? ? ? ? ? ? androidx.databinding.adapters.TextViewBindingAdapter.setText(this.tvName, userNameGet);
? ? ? ? ? ? this.tvToast.beishal(userNameGet);
? ? ? ? }
if ((dirtyFlags &0x61L) !=0) {
// api target 1
? ? ? ? ? ? androidx.databinding.adapters.TextViewBindingAdapter.setText(this.tvAge, stringValueOfUserAge);
? ? ? ? }
}
/////////////
? ? //回調(diào)流程////
/////////////
? ? /**
? ? * 1.observable基礎被觀察者類
? ? *? a.定義增加觀察者,移除觀察者
? ? *? b.內(nèi)部抽象類 定義通知方法格式 public abstract void onPropertyChanged(Observable sender, int propertyId);
? ? *? ? ? Observable sender: 對應平常自己定義的可觀察bean. 如UserBean( var age,var name)
? ? *? ? ? int propertyId :? 對應具體某一個字段 如 BR.name
* */
/**
* Observable classes provide a way in which data bound UI can be notified of changes.
? ? * {@link ObservableList} and {@link ObservableMap} also provide the ability to notify when
* changes occur. ObservableField, ObservableParcelable, ObservableBoolean, ObservableByte,
* ObservableShort, ObservableInt, ObservableLong, ObservableFloat, and ObservableDouble provide
* a means by which properties may be notified without implementing Observable.
? ? *
? ? * An Observable object should notify the {@link androidx.databinding.Observable.OnPropertyChangedCallback} whenever
* an observed property of the class changes.
? ? *
? ? * The getter for an observable property should be annotated with {@link Bindable}.
? ? *
? ? * Convenience class BaseObservable implements this interface and PropertyChangeRegistry
* can help classes that don't extend BaseObservable to implement the listener registry.
*/
? ? public interface Observable {
/**
* Adds a callback to listen for changes to the Observable.
? ? ? ? * @param callback The callback to start listening.
*/
? ? ? ? void addOnPropertyChangedCallback(androidx.databinding.Observable.OnPropertyChangedCallback callback);
? ? ? ? /**
* Removes a callback from those listening for changes.
? ? ? ? * @param callback The callback that should stop listening.
*/
? ? ? ? void removeOnPropertyChangedCallback(androidx.databinding.Observable.OnPropertyChangedCallback callback);
? ? ? ? /**
* The callback that is called by Observable when an observable property has changed.
*/
? ? ? ? abstract class OnPropertyChangedCallback {
/**
* Called by an Observable whenever an observable property changes.
? ? ? ? ? ? * @param sender The Observable that is changing.
? ? ? ? ? ? * @param propertyId The BR identifier of the property that has changed. The getter
? ? ? ? ? ? *? ? ? ? ? ? ? ? ? for this property should be annotated with {@link Bindable}.
*/
? ? ? ? ? ? public abstract void onPropertyChanged(androidx.databinding.Observable sender, int propertyId);
? ? ? ? }
}
/**
? ? * 2.BaseObservable 基礎被觀察類
? ? *? a.內(nèi)部分序列化對象: PropertyChangeRegistry ==>> 該類是對 被觀察者接口回調(diào)的管理類. 定義了怎么來進行回調(diào),怎么管理多個回調(diào)接口,調(diào)整接口數(shù)量等? ? ? Registry ==>> 表, 屬性變化注冊表
? ? *? ? ? a1. 對象得初始化是,每次添加回調(diào)時. 對應 mCallbacks = new PropertyChangeRegistry();? 該類具體后續(xù)分析
? ? *? b.添加和移除 觀察者回調(diào)
? ? *? c.豐富回調(diào)的調(diào)用
? ? *? ? ? c1. 通知具體某一個字段發(fā)生改變了? mCallbacks.notifyCallbacks(this, fieldId, null);
? ? *? ? ? c2. 通知該類下所有的字段發(fā)生變化了? mCallbacks.notifyCallbacks(this, 0, null);? ? this: 當前的被觀察者對象? fieldId : 具體字段id.
? ? *? ? ? c3. 這里會調(diào)用到 觀察者注冊表的notify方法
? ? *? 具體調(diào)用流程:
*? 1.ActivityMainBindingImpl.setUser(com.example.viewmodellearn.bean.User User)
? ? *? ? 1.1? updateRegistration(0,user) ==>> 這里是先注冊listener 暫時先不分析
? ? *? ? 1.2? notifyPropertyChanged(BR.user);(對應c1方法) 這里才是數(shù)據(jù)發(fā)生改變
? ? *? ? ? ? ? ? a.mCallbacks.notifyCallbacks(this, fieldId, null); (mCallback 對應下面的PropertyChangeRegistry)
? ? *? ? ? ? ? ? ? ? b.對應到notifyCallbacks(T sender, int arg, A arg2, final int startIndex,final int endIndex, final long bits); 這個方法. index.endindex ,bits暫時先不分析
? ? *? ? ? ? ? ? ? ? ? ? ? 其就是CallbackRegistry中具體定義的怎么回調(diào)? 對應調(diào)用處為 mNotifier.onNotifyCallback(mCallbacks.get(i), sender, arg, arg2);
*? ? ? ? ? ? ? ? ? ? c.mNotifier.onNotifyCallback(mCallbacks.get(i), sender, arg, arg2)
? ? *? ? ? ? ? ? ? ? ? ? ? ? ? mcallbacks.get(i) ==>> i 為需要回調(diào)的具體類 找到對應的回調(diào)類
? ? *? ? ? ? ? ? ? ? ? ? ? ? ? sender? ? ? ? ? ? ==>> 具體哪個bean對象 本文對應user
? ? *? ? ? ? ? ? ? ? ? ? ? ? ? arg? ? ? ? ? ? ? ==>> 對應具體的fileId 字段
? ? *? ? ? ? ? ? ? ? ? ? ? ? d. callback.onPropertyChanged(sender, arg);? 對應具體的回調(diào).
? ? *? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 通常 dataBinding里面會有默認的回調(diào)實現(xiàn). 本文分析以WeakPropertyListener 為主
? ? *? ? ? ? ? ? ? ? ? ? ? ? e.WeakPropertyListener繼承Observable.OnPropertyChangedCallback,實現(xiàn)了 onPorpertyChanged方法(Observable sender, int propertyId)
? ? *? ? ? ? ? 以上就是
? ? *
*
*
* */
/**
? ? * A convenience class that implements {@link androidx.databinding.Observable}
? ? * interface and provides {@link #notifyPropertyChanged(int)} and
? ? * {@link #notifyChange} methods.
*/
? ? public class BaseObservableimplements androidx.databinding.Observable {
private transient PropertyChangeRegistry mCallbacks;
? ? ? ? public BaseObservable() {
}
@Override
public void addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
synchronized (this) {
if (mCallbacks ==null) {
mCallbacks =new PropertyChangeRegistry();
? ? ? ? ? ? ? ? }
}
mCallbacks.add(callback);
? ? ? ? }
@Override
public void removeOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
synchronized (this) {
if (mCallbacks ==null) {
return;
? ? ? ? ? ? ? ? }
}
mCallbacks.remove(callback);
? ? ? ? }
/**
* Notifies listeners that all properties of this instance have changed.
*/
? ? ? ? public void notifyChange() {
synchronized (this) {
if (mCallbacks ==null) {
return;
? ? ? ? ? ? ? ? }
}
mCallbacks.notifyCallbacks(this, 0, null);
? ? ? ? }
/**
* Notifies listeners that a specific property has changed. The getter for the property
? ? ? ? * that changes should be marked with {@link Bindable} to generate a field in
? ? ? ? * <code>BR</code> to be used as <code>fieldId</code>.
*
? ? ? ? * @param fieldId The generated BR id for the Bindable field.
*/
? ? ? ? public void notifyPropertyChanged(int fieldId) {
synchronized (this) {
if (mCallbacks ==null) {
return;
? ? ? ? ? ? ? ? }
}
mCallbacks.notifyCallbacks(this, fieldId, null);
? ? ? ? }
}
/**
? ? * 3.觀察者注冊表(工具類)分析PropertyChangeRegistry的基礎類CallbackRegistry
*? CallbackRegistry
? ? *? ? a.暫時先不分析的功能
? ? *? ? ? a1.文檔介紹說, 當正在發(fā)出通知回調(diào)時,可進行對回調(diào)的修改,并不影響此處的進行
? ? *? ? ? a2.多個函數(shù)的方法
? ? *? ? b.NotifierCallback 靜態(tài)抽象內(nèi)部類, 該類規(guī)定了,回調(diào)管理器如何來進行回調(diào). 必須參數(shù)
? ? *? ? c.注意,b是構造函數(shù)里面的必傳參數(shù).
*
* */
/**
* A utility for storing and notifying callbacks. This class supports reentrant modification
* of the callbacks during notification without adversely disrupting notifications.
* A common pattern for callbacks is to receive a notification and then remove
* themselves. This class handles this behavior with constant memory under
* most circumstances.
*
? ? * <p>A subclass of {@link androidx.databinding.CallbackRegistry.NotifierCallback} must be passed to
* the constructor to define how notifications should be called. That implementation
* does the actual notification on the listener. It is typically a static instance
? ? * that can be reused for all similar CallbackRegistries.
? ? *
? ? * <p>This class supports only callbacks with at most three parameters.
* Typically, these are the notification originator and a parameter, with another to
* indicate which method to call, but these may be used as required. If more than
* three parameters are required or primitive types other than the single int provided
? ? * must be used, <code>A</code> should be some kind of containing structure that
? ? * the subclass may reuse between notifications.
? ? *
? ? * @param The callback type.
? ? * @param The notification sender type. Typically this is the containing class.
? ? * @param Opaque argument used to pass additional data beyond an int.
*/
? ? public class CallbackRegistryimplements Cloneable {
private static final String TAG ="CallbackRegistry";
? ? ? ? /** An ordered collection of listeners waiting to be notified. */
? ? ? ? private List mCallbacks =new ArrayList();
? ? ? ? /**
* A bit flag for the first 64 listeners that are removed during notification.
* The lowest significant bit corresponds to the 0th index into mCallbacks.
* For a small number of callbacks, no additional array of objects needs to
* be allocated.
*/
? ? ? ? private long mFirst64Removed =0x0;
? ? ? ? /**
* Bit flags for the remaining callbacks that are removed during notification.
* When there are more than 64 callbacks and one is marked for removal, a dynamic
* array of bits are allocated for the callbacks.
*/
? ? ? ? private long[] mRemainderRemoved;
? ? ? ? /** The recursion level of the notification */
? ? ? ? private int mNotificationLevel;
? ? ? ? /** The notification mechanism for notifying an event. */
? ? ? ? private final androidx.databinding.CallbackRegistry.NotifierCallback mNotifier;
? ? ? ? /**
* Creates an EventRegistry that notifies the event with notifier.
? ? ? ? * @param notifier The class to use to notify events.
*/
? ? ? ? public CallbackRegistry(androidx.databinding.CallbackRegistry.NotifierCallback notifier) {
mNotifier = notifier;
? ? ? ? }
/**
* Notify all callbacks.
*
? ? ? ? * @param sender The originator. This is an opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
? ? ? ? * @param arg An opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
? ? ? ? * @param arg2 An opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
*/
? ? ? ? public synchronized void notifyCallbacks(T sender, int arg, A arg2) {
mNotificationLevel++;
? ? ? ? ? ? notifyRecurse(sender, arg, arg2);
? ? ? ? ? ? mNotificationLevel--;
? ? ? ? ? ? if (mNotificationLevel ==0) {
if (mRemainderRemoved !=null) {
for (int i = mRemainderRemoved.length -1; i >=0; i--) {
final long removedBits = mRemainderRemoved[i];
? ? ? ? ? ? ? ? ? ? ? ? if (removedBits !=0) {
removeRemovedCallbacks((i +1) * Long.SIZE, removedBits);
? ? ? ? ? ? ? ? ? ? ? ? ? ? mRemainderRemoved[i] =0;
? ? ? ? ? ? ? ? ? ? ? ? }
}
}
if (mFirst64Removed !=0) {
removeRemovedCallbacks(0, mFirst64Removed);
? ? ? ? ? ? ? ? ? ? mFirst64Removed =0;
? ? ? ? ? ? ? ? }
}
}
/**
? ? ? ? * Notify up to the first Long.SIZE callbacks that don't have a bit set in <code>removed</code>.
*
? ? ? ? * @param sender The originator. This is an opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
? ? ? ? * @param arg An opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
? ? ? ? * @param arg2 An opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
*/
? ? ? ? private void notifyFirst64(T sender, int arg, A arg2) {
final int maxNotified = Math.min(Long.SIZE, mCallbacks.size());
? ? ? ? ? ? notifyCallbacks(sender, arg, arg2, 0, maxNotified, mFirst64Removed);
? ? ? ? }
/**
* Notify all callbacks using a recursive algorithm to avoid allocating on the heap.
* This part captures the callbacks beyond Long.SIZE that have no bits allocated for
? ? ? ? * removal before it recurses into {@link #notifyRemainder(Object, int, A, int)}.
*
? ? ? ? * <p>Recursion is used to avoid allocating temporary state on the heap.
? ? ? ? *
? ? ? ? * @param sender The originator. This is an opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
? ? ? ? * @param arg An opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
? ? ? ? * @param arg2 An opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
*/
? ? ? ? private void notifyRecurse(T sender, int arg, A arg2) {
final int callbackCount = mCallbacks.size();
? ? ? ? ? ? final int remainderIndex = mRemainderRemoved ==null ? -1 : mRemainderRemoved.length -1;
? ? ? ? ? ? // Now we've got all callbakcs that have no mRemainderRemoved value, so notify the
// others.
? ? ? ? ? ? notifyRemainder(sender, arg, arg2, remainderIndex);
? ? ? ? ? ? // notifyRemainder notifies all at maxIndex, so we'd normally start at maxIndex + 1
// However, we must also keep track of those in mFirst64Removed, so we add 2 instead:
? ? ? ? ? ? final int startCallbackIndex = (remainderIndex +2) * Long.SIZE;
? ? ? ? ? ? // The remaining have no bit set
? ? ? ? ? ? notifyCallbacks(sender, arg, arg2, startCallbackIndex, callbackCount, 0);
? ? ? ? }
/**
* Notify callbacks that have mRemainderRemoved bits set for remainderIndex. If
* remainderIndex is -1, the first 64 will be notified instead.
*
? ? ? ? * @param sender The originator. This is an opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
? ? ? ? * @param arg An opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
? ? ? ? * @param arg2 An opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
? ? ? ? * @param remainderIndex The index into mRemainderRemoved that should be notified.
*/
? ? ? ? private void notifyRemainder(T sender, int arg, A arg2, int remainderIndex) {
if (remainderIndex <0) {
notifyFirst64(sender, arg, arg2);
? ? ? ? ? ? }else {
final long bits = mRemainderRemoved[remainderIndex];
? ? ? ? ? ? ? ? final int startIndex = (remainderIndex +1) * Long.SIZE;
? ? ? ? ? ? ? ? final int endIndex = Math.min(mCallbacks.size(), startIndex + Long.SIZE);
? ? ? ? ? ? ? ? notifyRemainder(sender, arg, arg2, remainderIndex -1);
? ? ? ? ? ? ? ? notifyCallbacks(sender, arg, arg2, startIndex, endIndex, bits);
? ? ? ? ? ? }
}
/**
* Notify callbacks from startIndex to endIndex, using bits as the bit status
* for whether they have been removed or not. bits should be from mRemainderRemoved or
* mFirst64Removed. bits set to 0 indicates that all callbacks from startIndex to
* endIndex should be notified.
*
? ? ? ? * @param sender The originator. This is an opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
? ? ? ? * @param arg An opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
? ? ? ? * @param arg2 An opaque parameter passed to
? ? ? ? * {@link androidx.databinding.CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
? ? ? ? * @param startIndex The index into the mCallbacks to start notifying.
? ? ? ? * @param endIndex One past the last index into mCallbacks to notify.
? ? ? ? * @param bits A bit field indicating which callbacks have been removed and shouldn't
*? ? ? ? ? ? be notified.
*/
? ? ? ? private void notifyCallbacks(T sender, int arg, A arg2, final int startIndex,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? final int endIndex, final long bits) {
long bitMask =1;
? ? ? ? ? ? for (int i = startIndex; i < endIndex; i++) {
if ((bits & bitMask) ==0) {
mNotifier.onNotifyCallback(mCallbacks.get(i), sender, arg, arg2);
? ? ? ? ? ? ? ? }
bitMask <<=1;
? ? ? ? ? ? }
}
/**
* Add a callback to be notified. If the callback is already in the list, another won't
* be added. This does not affect current notifications.
? ? ? ? * @param callback The callback to add.
*/
? ? ? ? public synchronized void add(C callback) {
if (callback ==null) {
throw new IllegalArgumentException("callback cannot be null");
? ? ? ? ? ? }
int index = mCallbacks.lastIndexOf(callback);
? ? ? ? ? ? if (index <0 || isRemoved(index)) {
mCallbacks.add(callback);
? ? ? ? ? ? }
}
/**
* Returns true if the callback at index has been marked for removal.
*
? ? ? ? * @param index The index into mCallbacks to check.
? ? ? ? * @return true if the callback at index has been marked for removal.
*/
? ? ? ? private boolean isRemoved(int index) {
if (index < Long.SIZE) {
// It is in the first 64 callbacks, just check the bit.
? ? ? ? ? ? ? ? final long bitMask =1L << index;
? ? ? ? ? ? ? ? return (mFirst64Removed & bitMask) !=0;
? ? ? ? ? ? }else if (mRemainderRemoved ==null) {
// It is after the first 64 callbacks, but nothing else was marked for removal.
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }else {
final int maskIndex = (index / Long.SIZE) -1;
? ? ? ? ? ? ? ? if (maskIndex >= mRemainderRemoved.length) {
// There are some items in mRemainderRemoved, but nothing at the given index.
? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? }else {
// There is something marked for removal, so we have to check the bit.
? ? ? ? ? ? ? ? ? ? final long bits = mRemainderRemoved[maskIndex];
? ? ? ? ? ? ? ? ? ? final long bitMask =1L << (index % Long.SIZE);
? ? ? ? ? ? ? ? ? ? return (bits & bitMask) !=0;
? ? ? ? ? ? ? ? }
}
}
/**
* Removes callbacks from startIndex to startIndex + Long.SIZE, based
* on the bits set in removed.
*
? ? ? ? * @param startIndex The index into the mCallbacks to start removing callbacks.
? ? ? ? * @param removed The bits indicating removal, where each bit is set for one callback
*? ? ? ? ? ? ? ? to be removed.
*/
? ? ? ? private void removeRemovedCallbacks(int startIndex, long removed) {
// The naive approach should be fine. There may be a better bit-twiddling approach.
? ? ? ? ? ? final int endIndex = startIndex + Long.SIZE;
? ? ? ? ? ? long bitMask =1L << (Long.SIZE -1);
? ? ? ? ? ? for (int i = endIndex -1; i >= startIndex; i--) {
if ((removed & bitMask) !=0) {
mCallbacks.remove(i);
? ? ? ? ? ? ? ? }
bitMask >>>=1;
? ? ? ? ? ? }
}
/**
* Remove a callback. This callback won't be notified after this call completes.
*
? ? ? ? * @param callback The callback to remove.
*/
? ? ? ? public synchronized void remove(C callback) {
if (mNotificationLevel ==0) {
mCallbacks.remove(callback);
? ? ? ? ? ? }else {
int index = mCallbacks.lastIndexOf(callback);
? ? ? ? ? ? ? ? if (index >=0) {
setRemovalBit(index);
? ? ? ? ? ? ? ? }
}
}
private void setRemovalBit(int index) {
if (index < Long.SIZE) {
// It is in the first 64 callbacks, just check the bit.
? ? ? ? ? ? ? ? final long bitMask =1L << index; //
? ? ? ? ? ? ? ? mFirst64Removed |= bitMask;
? ? ? ? ? ? }else {
final int remainderIndex = (index / Long.SIZE) -1;
? ? ? ? ? ? ? ? if (mRemainderRemoved ==null) {
mRemainderRemoved =new long[mCallbacks.size() / Long.SIZE];
? ? ? ? ? ? ? ? }else if (mRemainderRemoved.length <= remainderIndex) {
// need to make it bigger
? ? ? ? ? ? ? ? ? ? long[] newRemainders =new long[mCallbacks.size() / Long.SIZE];
? ? ? ? ? ? ? ? ? ? System.arraycopy(mRemainderRemoved, 0, newRemainders, 0, mRemainderRemoved.length);
? ? ? ? ? ? ? ? ? ? mRemainderRemoved = newRemainders;
? ? ? ? ? ? ? ? }
final long bitMask =1L << (index % Long.SIZE);
? ? ? ? ? ? ? ? mRemainderRemoved[remainderIndex] |= bitMask;
? ? ? ? ? ? }
}
/**
* Makes a copy of the registered callbacks and returns it.
*
? ? ? ? * @return a copy of the registered callbacks.
*/
? ? ? ? public synchronized ArrayList copyCallbacks() {
ArrayList callbacks =new ArrayList(mCallbacks.size());
? ? ? ? ? ? int numListeners = mCallbacks.size();
? ? ? ? ? ? for (int i =0; i < numListeners; i++) {
if (!isRemoved(i)) {
callbacks.add(mCallbacks.get(i));
? ? ? ? ? ? ? ? }
}
return callbacks;
? ? ? ? }
/**
? ? ? ? * Modifies <code>callbacks</code> to contain all callbacks in the CallbackRegistry.
*
? ? ? ? * @param callbacks modified to contain all callbacks registered to receive events.
*/
? ? ? ? public synchronized void copyCallbacks(List callbacks) {
callbacks.clear();
? ? ? ? ? ? int numListeners = mCallbacks.size();
? ? ? ? ? ? for (int i =0; i < numListeners; i++) {
if (!isRemoved(i)) {
callbacks.add(mCallbacks.get(i));
? ? ? ? ? ? ? ? }
}
}
/**
* Returns true if there are no registered callbacks or false otherwise.
*
? ? ? ? * @return true if there are no registered callbacks or false otherwise.
*/
? ? ? ? public synchronized boolean isEmpty() {
if (mCallbacks.isEmpty()) {
return true;
? ? ? ? ? ? }else if (mNotificationLevel ==0) {
return false;
? ? ? ? ? ? }else {
int numListeners = mCallbacks.size();
? ? ? ? ? ? ? ? for (int i =0; i < numListeners; i++) {
if (!isRemoved(i)) {
return false;
? ? ? ? ? ? ? ? ? ? }
}
return true;
? ? ? ? ? ? }
}
/**
* Removes all callbacks from the list.
*/
? ? ? ? public synchronized void clear() {
if (mNotificationLevel ==0) {
mCallbacks.clear();
? ? ? ? ? ? }else if (!mCallbacks.isEmpty()) {
for (int i = mCallbacks.size() -1; i >=0; i--) {
setRemovalBit(i);
? ? ? ? ? ? ? ? }
}
}
/**
? ? ? ? * @return A copy of the CallbackRegistry with all callbacks listening to both instances.
*/
? ? ? ? @Override
@SuppressWarnings("unchecked")
public synchronized androidx.databinding.CallbackRegistry clone() {
androidx.databinding.CallbackRegistry clone =null;
? ? ? ? ? ? try {
clone = (androidx.databinding.CallbackRegistry)super.clone();
? ? ? ? ? ? ? ? clone.mFirst64Removed =0;
? ? ? ? ? ? ? ? clone.mRemainderRemoved =null;
? ? ? ? ? ? ? ? clone.mNotificationLevel =0;
? ? ? ? ? ? ? ? clone.mCallbacks =new ArrayList();
? ? ? ? ? ? ? ? final int numListeners = mCallbacks.size();
? ? ? ? ? ? ? ? for (int i =0; i < numListeners; i++) {
if (!isRemoved(i)) {
clone.mCallbacks.add(mCallbacks.get(i));
? ? ? ? ? ? ? ? ? ? }
}
}catch (CloneNotSupportedException e) {
e.printStackTrace();
? ? ? ? ? ? }
return clone;
? ? ? ? }
/**
* Class used to notify events from CallbackRegistry.
*
? ? ? ? * @param The callback type.
? ? ? ? * @param The notification sender type. Typically this is the containing class.
? ? ? ? * @param An opaque argument to pass to the notifier
*/
? ? ? ? public abstract static class NotifierCallback {
/**
* Called by CallbackRegistry during
? ? ? ? ? ? * {@link androidx.databinding.CallbackRegistry#notifyCallbacks(Object, int, Object)}} to notify the callback.
*
? ? ? ? ? ? * @param callback The callback to notify.
? ? ? ? ? ? * @param sender The opaque sender object.
? ? ? ? ? ? * @param arg The opaque notification parameter.
? ? ? ? ? ? * @param arg2 An opaque argument passed in
? ? ? ? ? ? *? ? ? ? {@link androidx.databinding.CallbackRegistry#notifyCallbacks}
? ? ? ? ? ? * @see androidx.databinding.CallbackRegistry#CallbackRegistry(androidx.databinding.CallbackRegistry.NotifierCallback)
*/
? ? ? ? ? ? public abstract void onNotifyCallback(C callback, T sender, int arg, A arg2);
? ? ? ? }
}
/**
? ? * 4.觀察者注冊表具體實現(xiàn)PropertyChangeRegistry
? ? *? a.CallbackRegistry.NotifierCallback<Observable.OnPropertyChangedCallback, Observable, Void> NOTIFIER_CALLBACK
? ? *? ? ? a1.靜態(tài)內(nèi)部類 定義了怎么來進行回調(diào)處理.? 本類中方法比較簡單,就是 callback.onPropertyChanged(sender,age);
? ? *? b.notifyChange(@NonNull Observable observable, int propertyId) 暫時沒發(fā)現(xiàn)哪里在使用. 暫不分析
? ? * */
? ? public class PropertyChangeRegistryextends androidx.databinding.CallbackRegistry {
private static final NotifierCallback NOTIFIER_CALLBACK =new NotifierCallback() {
public void onNotifyCallback(androidx.databinding.Observable.OnPropertyChangedCallback callback, androidx.databinding.Observable sender, int arg, Void notUsed) {
callback.onPropertyChanged(sender, arg);
? ? ? ? ? ? }
};
? ? ? ? public PropertyChangeRegistry() {
super(NOTIFIER_CALLBACK);
? ? ? ? }
public void notifyChange(@NonNull androidx.databinding.Observable observable, int propertyId) {
this.notifyCallbacks(observable, propertyId, (Object)null);
? ? ? ? }
}
/**
? ? * 1.參數(shù)
? ? * DataBindingComponent bindingComponent? :這個暫時不看
? ? * view? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? :需要處理的那個view
? ? * Object[] bindings? ? ? ? ? ? ? ? ? ? ? :所有view的集合
? ? * ViewDataBinding.IncludedLayouts includes:用來處理嵌套view
? ? * SparseIntArray viewsWithIds? ? ? ? ? ? :key 是view的聲明id, value是在bindings集合的序號? 這個是用來存放沒有綁定的view.
? ? * boolean isRoot? ? ? ? ? ? ? ? ? ? ? ? ? :是不是根節(jié)點
? ? *
* 2.
? ? * 再細節(jié)的代碼就不知道了....
*
? ? * 這里 a.binds[] b.
* 3.
* */
? ? private static void mapBindings(DataBindingComponent bindingComponent, View view,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Object[] bindings, ViewDataBinding.IncludedLayouts includes, SparseIntArray viewsWithIds,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? boolean isRoot) {
final int indexInIncludes;
? ? ? ? final ViewDataBinding existingBinding = getBinding(view);// 已經(jīng)處理過后不再處理
? ? ? ? if (existingBinding !=null) {
return;
? ? ? ? }
Object objTag = view.getTag();
? ? ? ? final String tag = (objTaginstanceof String) ? (String) objTag :null;
? ? ? ? boolean isBound =false;
? ? ? ? // 最外層的layout ==>> 處理
? ? ? ? if (isRoot && tag !=null && tag.startsWith("layout")) {
// _的下角標
? ? ? ? ? ? final int underscoreIndex = tag.lastIndexOf('_');
? ? ? ? ? ? // 剩下的是一個數(shù)字,并且該數(shù)字大于0 ==>> 證明是有
? ? ? ? ? ? if (underscoreIndex >0 && isNumeric(tag, underscoreIndex +1)) {
final int index = parseTagInt(tag, underscoreIndex +1);
? ? ? ? ? ? ? ? // 存放到bindings集合中
? ? ? ? ? ? ? ? if (bindings[index] ==null) {
bindings[index] = view;
? ? ? ? ? ? ? ? }
// 如果子 雙維集合不為空,當前的view對應的角標 就是集合上的角標
? ? ? ? ? ? ? ? indexInIncludes = includes ==null ? -1 : index;
? ? ? ? ? ? ? ? isBound =true;
? ? ? ? ? ? }else {
indexInIncludes = -1;
? ? ? ? ? ? }
//? 同樣的道理,對子view進行處理
? ? ? ? }else if (tag !=null && tag.startsWith(BINDING_TAG_PREFIX)) {
int tagIndex = parseTagInt(tag, BINDING_NUMBER_START);
? ? ? ? ? ? if (bindings[tagIndex] ==null) {
bindings[tagIndex] = view;
? ? ? ? ? ? }
isBound =true;
? ? ? ? ? ? indexInIncludes = includes ==null ? -1 : tagIndex;
? ? ? ? }else {
// Not a bound view
? ? ? ? ? ? indexInIncludes = -1;
? ? ? ? }
// 如果不是bindingView,存放規(guī)則
? ? ? ? if (!isBound) {
final int id = view.getId();
? ? ? ? ? ? if (id >0) {
int index;
? ? ? ? ? ? ? ? // 非綁定的veiw,這里是只有存儲過的,才會進行存放.
? ? ? ? ? ? ? ? if (viewsWithIds !=null && (index = viewsWithIds.get(id, -1)) >=0 &&
bindings[index] ==null) {
bindings[index] = view;
? ? ? ? ? ? ? ? }
}
}
// 對子view的處理
? ? ? ? if (viewinstanceof ViewGroup) {
final ViewGroup viewGroup = (ViewGroup) view;
? ? ? ? ? ? final int count = viewGroup.getChildCount();
? ? ? ? ? ? int minInclude =0;
? ? ? ? ? ? for (int i =0; i < count; i++) {
final View child = viewGroup.getChildAt(i);
? ? ? ? ? ? ? ? boolean isInclude =false;
? ? ? ? ? ? ? ? // 如果這個view 是bindview.
? ? ? ? ? ? ? ? if (indexInIncludes >=0 && child.getTag()instanceof String) {
String childTag = (String) child.getTag();
? ? ? ? ? ? ? ? ? ? // 第一個子View? layout? /? _0
//
? ? ? ? ? ? ? ? ? ? if (childTag.endsWith("_0") &&
childTag.startsWith("layout") && childTag.indexOf('/') >0) {
// This *could* be an include. Test against the expected includes.
? ? ? ? ? ? ? ? ? ? ? ? int includeIndex = findIncludeIndex(childTag, minInclude,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? includes, indexInIncludes);
? ? ? ? ? ? ? ? ? ? ? ? if (includeIndex >=0) {
isInclude =true;
? ? ? ? ? ? ? ? ? ? ? ? ? ? minInclude = includeIndex +1;
? ? ? ? ? ? ? ? ? ? ? ? ? ? final int index = includes.indexes[indexInIncludes][includeIndex];
? ? ? ? ? ? ? ? ? ? ? ? ? ? final int layoutId = includes.layoutIds[indexInIncludes][includeIndex];
? ? ? ? ? ? ? ? ? ? ? ? ? ? int lastMatchingIndex = findLastMatching(viewGroup, i);
? ? ? ? ? ? ? ? ? ? ? ? ? ? if (lastMatchingIndex == i) {
bindings[index] = DataBindingUtil.bind(bindingComponent, child,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? layoutId);
? ? ? ? ? ? ? ? ? ? ? ? ? ? }else {
final int includeCount =? lastMatchingIndex - i +1;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? final View[] included =new View[includeCount];
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? for (int j =0; j < includeCount; j++) {
included[j] = viewGroup.getChildAt(i + j);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
bindings[index] = DataBindingUtil.bind(bindingComponent, included,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? layoutId);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? i += includeCount -1;
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
}
}
}
if (!isInclude) {
mapBindings(bindingComponent, child, bindings, includes, viewsWithIds, false);
? ? ? ? ? ? ? ? }
}
}
}
/**
? ? * 1.怎么確認子View的集合序列
? ? *
? ? *? tag? ? ? ? ? : view中的tag? binding_
? ? *? minInclude? ? : 起點
? ? *? included? ? ? : 用來存放子view對應的集合
? ? *? includedIndex : 父節(jié)點view在bindings集合中的角標
? ? * */
? ? private static int findIncludeIndex(String tag, int minInclude,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ViewDataBinding.IncludedLayouts included, int includedIndex) {
final int slashIndex = tag.indexOf('/');
? ? ? ? // 拿到layoutname
? ? ? ? final CharSequence layoutName = tag.subSequence(slashIndex +1, tag.length() -2);
? ? ? ? // 先處理layout
? ? ? ? final String[] layouts = included.layouts[includedIndex];
? ? ? ? // 1.如果有緩存了,那就返回具體的角標
? ? ? ? // 2.如果沒有緩存,就返回-1,標識沒有.
? ? ? ? final int length = layouts.length;
? ? ? ? for (int i = minInclude; i < length; i++) {
final String layout = layouts[i];
? ? ? ? ? ? if (TextUtils.equals(layoutName, layout)) {
return i;
? ? ? ? ? ? }
}
return -1;
? ? }
/**
? ? * 1.BindingAdapter注解
? ? *? a.用來對一個view進行 屬性的賦值 怎么來進行賦值? setter方法
? ? *? b.如果有老的屬性, 新老屬性的交替??? 這里沒有理解 ==>> 等待怎么使用 相同的一個屬性
? ? *? c.不同的屬性,不同的交互方式. ==>> 多個參數(shù)
? ? *? d.除了靜態(tài)方法來使用這個; 也可以使用一個實例來實現(xiàn)這個方法,但是要引入這個實例.
* */
? ? //1. 初始化函數(shù)中,這里進行了一次綁定invalidate()
? ? @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
protected boolean updateRegistration(int localFieldId, Object observable,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? androidx.databinding.CreateWeakListener listenerCreator) {
//source數(shù)據(jù)源為空,移除對應的listener
? ? ? ? if (observable ==null) {不為空
? ? ? ? ? ? return unregisterFrom(localFieldId);
? ? ? ? }
androidx.databinding.WeakListener listener = mLocalFieldObservers[localFieldId];
? ? ? ? if (listener ==null) {不為空
? ? ? ? ? ? // 更新觀察者
? ? ? ? ? ? registerTo(localFieldId, observable, listenerCreator);
return true;
? ? ? ? }
// 不為空時,并且相同,暫時不需要進行更新
? ? ? ? if (listener.getTarget() == observable) {
return false;//nothing to do, same object
? ? ? ? }
// 不相同
? ? ? ? // 走到這里的時候,就要對 id,source,listener進行更新
? ? ? ? //移除
? ? ? ? unregisterFrom(localFieldId);
? ? ? ? //進行注冊
? ? ? ? registerTo(localFieldId, observable, listenerCreator);
return true;
? ? }
/**
? ? * layoutdatabinding幾個注冊觀察者互相通知
? ? * */
? ? //創(chuàng)建的時候
? ? //綁定過程中的幾個方法? 和? 遍歷的時候 移除對應的listener
? ? //以及對應的生命周期
? ? /**
? ? * 第一步: 先介紹幾個bind的方法
? ? * */
/**
? ? * 1.程序初始化的時候調(diào)用....
* */
? ? protected void requestRebind() {
if (mContainingBinding !=null) {
mContainingBinding.requestRebind();
? ? ? ? }else {
// 生命周期 沒有展示的 就不再繼續(xù)處理
? ? ? ? ? ? final LifecycleOwner owner =this.mLifecycleOwner;
? ? ? ? ? ? if (owner !=null) {
Lifecycle.State state = owner.getLifecycle().getCurrentState();
? ? ? ? ? ? ? ? if (!state.isAtLeast(Lifecycle.State.STARTED)) {
return; // wait until lifecycle owner is started
? ? ? ? ? ? ? ? }
}
// 已經(jīng)有人要執(zhí)行綁定了 ==>> 這里就不再觸發(fā)了.? 本次猜測標識符的一個完整周期? 第一次使用? ? 然后等 doFrame 回來以后,把這個變成false. ===>> 經(jīng)過驗證就是這么一回事兒
? ? ? ? ? ? synchronized (this) {
if (mPendingRebind) {
return;
? ? ? ? ? ? ? ? }
mPendingRebind =true;
? ? ? ? ? ? }
// 現(xiàn)在的android都是用 vsync垂直信號來進行處理的
? ? ? ? ? ? if (USE_CHOREOGRAPHER) {
// 60FPS 這中間還有空隙 ==>>? ? 結合一次setUser()這種改變過程來看一下 mPendingRebind 和 regestiry 監(jiān)聽工具包里面的作用 ==>> 防止并發(fā) 去重
? ? ? ? ? ? ? ? mChoreographer.postFrameCallback(mFrameCallback);
? ? ? ? ? ? }else {
mUIThreadHandler.post(mRebindRunnable);
? ? ? ? ? ? }
}
}
/**
? ? * 2.看下runnable 具體任務
? ? * */
? ? private final Runnable mRebindRunnable =new Runnable() {
@Override
public void run() {
// 具體對應的開頭的? requestRebind ,開啟一次綁定
? ? ? ? ? ? synchronized (this) {
mPendingRebind =false;
? ? ? ? ? ? }
// 防止內(nèi)存泄漏
? ? ? ? ? ? processReferenceQueue();
? ? ? ? ? ? // 沒有渲染的view不進行處理
? ? ? ? ? ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// Nested so that we don't get a lint warning in IntelliJ
? ? ? ? ? ? ? ? if (!mRoot.isAttachedToWindow()) {
// Don't execute the pending bindings until the View
// is attached again.
? ? ? ? ? ? ? ? ? ? mRoot.removeOnAttachStateChangeListener(ROOT_REATTACHED_LISTENER);
? ? ? ? ? ? ? ? ? ? mRoot.addOnAttachStateChangeListener(ROOT_REATTACHED_LISTENER);
return;
? ? ? ? ? ? ? ? }
}
// 開始執(zhí)行需要進行的binding
? ? ? ? ? ? executePendingBindings();
? ? ? ? }
};
? ? /**
? ? * 3. 需要進行的綁定 (view? 和 include view 的綁定)
* */
? ? public void executePendingBindings() {
if (mContainingBinding ==null) {
executeBindingsInternal();
? ? ? ? }else {
mContainingBinding.executePendingBindings();
? ? ? ? }
}
/**
? ? * 4. 內(nèi)部真正執(zhí)行綁定的地方
? ? * */
? ? private void executeBindingsInternal() {
// 這里怎么能走到并發(fā)呢?? ==>> 有可能executeBinding的時候比較耗時 ==>>> 導致這里還在進行;
? ? ? ? if (mIsExecutingPendingBindings) {
requestRebind();
return;
? ? ? ? }
// 查看一下ditryFlags? 沒有需要綁定處理的時候, 不再繼續(xù)執(zhí)行!
? ? ? ? if (!hasPendingBindings()) {
return;
? ? ? ? }
mIsExecutingPendingBindings =true;
? ? ? ? // rebindHalted 這個參數(shù)的含義? todo 驗證一下 rebindHalted 這個標識符所代表的的邏輯
? ? ? ? mRebindHalted =false;
? ? ? ? if (mRebindCallbacks !=null) {
mRebindCallbacks.notifyCallbacks(this, REBIND, null);
? ? ? ? ? ? // The onRebindListeners will change mPendingHalted
? ? ? ? ? ? if (mRebindHalted) {
mRebindCallbacks.notifyCallbacks(this, HALTED, null);
? ? ? ? ? ? }
}
// 這里的回調(diào)怎么處理
? ? ? ? if (!mRebindHalted) {
executeBindings();
? ? ? ? ? ? if (mRebindCallbacks !=null) {
mRebindCallbacks.notifyCallbacks(this, REBOUND, null);
? ? ? ? ? ? }
}
mIsExecutingPendingBindings =false;
? ? }
/**
? ? * 5. executeBindings 實際綁定的地方
? ? * */
? ? protected void executeBindings() {
long dirtyFlags =0;
? ? ? ? synchronized(this) {
dirtyFlags = mDirtyFlags;
? ? ? ? ? ? mDirtyFlags =0;
? ? ? ? }
java.lang.String userName =null;
? ? ? ? int userAge =0;
? ? ? ? com.example.myapplication.bean.UserBean user = mUser;
? ? ? ? if ((dirtyFlags &0x1dL) !=0) {
if ((dirtyFlags &0x19L) !=0) {
if (user !=null) {
// read user.name
? ? ? ? ? ? ? ? ? ? userName = user.getName();
? ? ? ? ? ? ? ? }
}
if ((dirtyFlags &0x15L) !=0) {
if (user !=null) {
// read user.age
? ? ? ? ? ? ? ? ? ? userAge = user.getAge();
? ? ? ? ? ? ? ? }
}
}
// batch finished
? ? ? ? if ((dirtyFlags &0x19L) !=0) {
// api target 1
? ? ? ? ? ? androidx.databinding.adapters.TextViewBindingAdapter.setText(this.tv, userName);
? ? ? ? }
if ((dirtyFlags &0x10L) !=0) {
// api target 1
? ? ? ? ? ? androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.tv, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, tvandroidTextAttrChanged);
? ? ? ? ? ? com.example.myapplication.customeView.DragView.seeCent(this.tv1, tv1onTextChanged);
? ? ? ? }
if ((dirtyFlags &0x15L) !=0) {
// api target 1
? ? ? ? ? ? com.example.myapplication.customeView.DragView.setCen1(this.tv1, userAge);
? ? ? ? }
}
/**
? ? *? 第二步: 看一下手動調(diào)用setUser這里的流程? 其實就是怎么觸發(fā)通知的!
* */
/**
? ? * 1. 設置數(shù)據(jù)源改變
? ? * */
? ? public void setUser(@Nullable com.example.myapplication.bean.UserBean User) {
//注冊觀察者
? ? ? ? updateRegistration(0, User);
? ? ? ? this.mUser = User;
? ? ? ? //設定標識位
? ? ? ? synchronized(this) {
mDirtyFlags |=0x1L;
? ? ? ? }
// 通知一下對應callBack? onchange(); ==>> 設定UI
? ? ? ? // 通知
? ? ? ? notifyPropertyChanged(BR.user);
? ? ? ? // 又一次要進行綁定
? ? ? ? super.requestRebind();
? ? }
/**
? ? * 2. 觀察者的調(diào)用
? ? * */
? ? public void notifyPropertyChanged(int fieldId) {
synchronized (this) {
if (mCallbacks ==null) {
return;
? ? ? ? ? ? }
}
mCallbacks.notifyCallbacks(this, fieldId, null);
? ? }
/**
? ? * 3. 轉化到具體的回調(diào)監(jiān)聽處 (本處以WeakPropertyListener為例來介紹)
* */
? ? @Override
public void onPropertyChanged(androidx.databinding.Observable sender, int propertyId) {
ViewDataBinding binder = mListener.getBinder();
? ? ? ? if (binder ==null) {
return;
? ? ? ? }
androidx.databinding.Observable obj = mListener.getTarget();
? ? ? ? if (obj != sender) {
return; // notification from the wrong object?
? ? ? ? }
binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
? ? }
/**
? ? * 4. 處理改變
? ? * */
? ? @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
protected void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
if (mInLiveDataRegisterObserver || mInStateFlowRegisterObserver) {
// We're in LiveData or StateFlow registration, which always results in a field change
// that we can ignore. The value will be read immediately after anyway, so
// there is no need to be dirty.
? ? ? ? ? ? return;
? ? ? ? }
boolean result = onFieldChange(mLocalFieldId, object, fieldId);
? ? ? ? if (result) {
requestRebind();
? ? ? ? }
}
/**
? ? * 5. 是否還需要綁定? ==>> onFileChange 這里 all. age? name 綁定的了!!! 那如果notify其他的呢?????? 驗證一下 notify其他的一個id ==>> 這里不生效...
* */
/**
? ? * 是否需要重新綁定的邏輯
? ? * */
? ? private void executeBindingsInternal() {
if (mIsExecutingPendingBindings) {
requestRebind();
return;
? ? ? ? }
if (!hasPendingBindings()) {
return;
? ? ? ? }
mIsExecutingPendingBindings =true;
? ? ? ? // 基本都是不停下來
? ? ? ? mRebindHalted =false;
? ? ? ? // 有沒有重新綁定的回調(diào)==>>
? ? ? ? if (mRebindCallbacks !=null) {
// 告訴需要重新綁定
? ? ? ? ? ? mRebindCallbacks.notifyCallbacks(this, REBIND, null);
? ? ? ? ? ? // The onRebindListeners will change mPendingHalted
? ? ? ? ? ? if (mRebindHalted) {
mRebindCallbacks.notifyCallbacks(this, HALTED, null);
? ? ? ? ? ? }
}
if (!mRebindHalted) {
executeBindings();
? ? ? ? ? ? if (mRebindCallbacks !=null) {
mRebindCallbacks.notifyCallbacks(this, REBOUND, null);
? ? ? ? ? ? }
}
mIsExecutingPendingBindings =false;
? ? }
/**
*
* */
? ? private static final androidx.databinding.CallbackRegistry.NotifierCallback
REBIND_NOTIFIER =new androidx.databinding.CallbackRegistry.NotifierCallback() {
@Override
public void onNotifyCallback(OnRebindCallback callback, ViewDataBinding sender, int mode,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Void arg2) {
switch (mode) {
case REBIND:
// 需要重新綁定的時候
? ? ? ? ? ? ? ? ? ? /**
? ? ? ? ? ? ? ? ? ? * 1.綁定時,值不穩(wěn)定, 需要重新rebind時
? ? ? ? ? ? ? ? ? ? * */
? ? ? ? ? ? ? ? ? ? // 如若 提前綁定表明 true, 說明需要重新賦值時
? ? ? ? ? ? ? ? ? ? // 最后 binding完以后? 就會調(diào)用onBound ()
? ? ? ? ? ? ? ? ? ? /**
? ? ? ? ? ? ? ? ? ? * 2.綁定時,值不穩(wěn)定,但是不需要重新綁定時. datebinding就失效了!!!!!!
* */
? ? ? ? ? ? ? ? ? ? // 如果不能綁定 onPreBind 返回false
? ? ? ? ? ? ? ? ? ? // 此時外層綁定值變成true? ==>>
? ? ? ? ? ? ? ? ? ? // 回調(diào)binding已經(jīng)停止 ==>> rebinding 調(diào)用cancel取消了.
? ? ? ? ? ? ? ? ? ? if (!callback.onPreBind(sender)) {
sender.mRebindHalted =true;
? ? ? ? ? ? ? ? ? ? }
break;
? ? ? ? ? ? ? ? case HALTED:
callback.onCanceled(sender);
break;
? ? ? ? ? ? ? ? case REBOUND:
callback.onBound(sender);
break;
? ? ? ? ? ? }
}
};
? ? /**
? ? * 體驗一下使用 databindingComponete來實現(xiàn) 動態(tài)換膚,測試代碼,進行埋點等
? ? *
* */
/**
* The DataBindingComponent used by this data binding. This is used for BindingAdapters
* that are instance methods to retrieve the class instance that implements the
* adapter.
*
? ? * @hide
? ? */
? ? protected final DataBindingComponent mBindingComponent;
}