setContentView
在Activity中使用的時候,先綁定佈局文件,那麼這個操作都做了什麼?我們從源碼中找答案
ActivityMainBinding binding= DataBindingUtil.setContentView(this,R.layout.activity_main)
在這個方法中,注意contentView是系統佈局DecorView中的content節點,layoutId是當前Activity的佈局id
public static <T extends ViewDataBinding> T setContentView(@NonNull Activity activity,
int layoutId, @Nullable DataBindingComponent bindingComponent) {
activity.setContentView(layoutId);
View decorView = activity.getWindow().getDecorView();
ViewGroup contentView = (ViewGroup) decorView.findViewById(android.R.id.content);
return bindToAddedViews(bindingComponent, contentView, 0, layoutId);
}
這裏childrenAdded正常情況下必須是1,因爲parent是系統的content節點,而使用databing,我們自己寫的佈局的根結點需要是一個<layout>
private static <T extends ViewDataBinding> T bindToAddedViews(DataBindingComponent component,
ViewGroup parent, int startChildren, int layoutId) {
final int endChildren = parent.getChildCount();
final int childrenAdded = endChildren - startChildren;
if (childrenAdded == 1) {
final View childView = parent.getChildAt(endChildren - 1);
return bind(component, childView, layoutId);
} else {
final View[] children = new View[childrenAdded];
for (int i = 0; i < childrenAdded; i++) {
children[i] = parent.getChildAt(i + startChildren);
}
return bind(component, children, layoutId);
}
}
繼續往下就進入到了com.項目路徑.DataBinderMapperImpl類中,在getDataBinder中可以看到,返回了ActivityMainBindingImpl
@Override
public ViewDataBinding getDataBinder(DataBindingComponent component, View view, int layoutId) {
int localizedLayoutId = INTERNAL_LAYOUT_ID_LOOKUP.get(layoutId);
if(localizedLayoutId > 0) {
final Object tag = view.getTag();
if(tag == null) {
throw new RuntimeException("view must have a tag");
}
switch(localizedLayoutId) {
case LAYOUT_ACTIVITYMAIN: {
if ("layout/activity_main_0".equals(tag)) {
return new ActivityMainBindingImpl(component, view);
}
throw new IllegalArgumentException("The tag for activity_main is invalid. Received: " + tag);
}
}
}
return null;
}
而在構造ActivityMainBindingImpl的時候可以看出,在mapBindings方法中,將佈局中的子節點保存在了數組中,於是通過binding對象就可以取到這些節點了如:binding.tv1
public ActivityMainBindingImpl(@Nullable androidx.databinding.DataBindingComponent bindingComponent, @NonNull View root) {
this(bindingComponent, root, mapBindings(bindingComponent, root, 3, sIncludes, sViewsWithIds));
}