1. 程式人生 > >Android View類的四個建構函式-面試時總被問到

Android View類的四個建構函式-面試時總被問到

/**
 * 從程式碼建立檢視時使用的簡單建構函式.即在程式碼中new View(context);
 *
 * @param context 上下文引數
 */
public View(Context context) {
mContext = context;
mResources = context != null ? context.getResources() : null;
...
//獲得系統提供的識別使用者是否觸發了move的最小距離值
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
...
}


/**
 * 噹噹前view使用xml方式inflating建立時,呼叫該建構函式。
 * 並且提供在XML檔案中指定的自定義屬性。
 * 此建構函式使用預設樣式為0,因此建立的view是有自定義屬性和系統提供的預設theme屬性可用。
 *
 * <p>
 * onFinishInflate()方法將會在所有的children被新增完成時呼叫,即xml解析完成時呼叫。
 * @param context 上下文
 * @param attrs 自定義屬性.
 * @see 參考三個引數的建構函式#View(Context, AttributeSet, int)
 */
public View(Context context, @Nullable AttributeSet attrs) {
//呼叫當前類三個引數的建構函式
this(context, attrs, 0);
}


/**
 * 執行xml載入的方式建立view,同時運用android:theme屬性給定的主題樣式屬性值。
 * 這個檢視建構函式允許子類在膨脹時使用自己的基本樣式。
 * 例如, 一個Button類的建構函式將會執行父類的,
 * 同時申請R.attr.buttonStyle樣式通過defStyleAttr引數值
 * 這允許主題的按鈕樣式修改所有基本檢視屬性(特別是它的背景)以及按鈕類的屬性。
 *
 * @param context 上下文.
 * @param attrs 正在載入檢視的XML標記的屬性.
 * @param defStyleAttr 當前主題中的一個屬性,該屬性包含對提供檢視預設值的樣式資源的引用。可以是0不查詢預設值。
 * @see #View(Context, AttributeSet)
 */
public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
//呼叫當前類4個引數的建構函式
this(context, attrs, defStyleAttr, 0);
}


/**
 * 從XML執行載入view,並從主題屬性或樣式資源中應用特定於類的基本樣式。
 * 這個檢視建構函式允許子類在載入時使用自己的基本樣式。
 * <p>
 * 當確定一個特定的屬性值時,有些面作用順序,即作用優先順序:
 * <ol>
 * <li>1、控制元件給定的屬性集合AttributeSet.
 * <li>2、在xml中style屬性值給定屬性集合AttributeSet.
 * <li>3、通過defStyleAttr屬性值給定的預設樣式值.
 * <li>4、通過defStyleRes屬性值給定的預設樣式值.
 * <li>5、此主題中的基值.
 * </ol>
 * <p>
 * 上面的12345點,都是經過熟慮且排序的, 即前面的值或覆蓋後面的值. 
 * 換句話說,在AttributeSet中定義了一個textColor="#ff000000"值,
 * 那麼這個控制元件的文字永遠都是黑色的,不改你再上面的2345等屬性中設定什麼樣的值。
 *
 * @param context 上下文.
 * @param attrs 正在載入檢視的XML標記的屬性。
 * @param defStyleAttr 當前主題中的一個屬性,該屬性包含對提供檢視預設值的樣式資源的引用。可以是0不查詢預設值。
 * @param defStyleRes 一個提供檢視預設值的樣式資源的識別符號,僅僅在defStyleAttr為0或者defStyleAttr在theme中找不到時使用。
 *        如果defStyleRes值為0,則不使用該屬性值。
 * @see #View(Context, AttributeSet, int)
 */
public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
//呼叫了一個引數的建構函式程式碼,同時執行後續程式碼
this(context);


//獲取自定義屬性
final TypedArray a = context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);


if (mDebugViewAttributes) {
saveAttributeData(attrs, a);
}


Drawable background = null;


//初始化各種變數或物件
int leftPadding = -1;
int topPadding = -1;
int rightPadding = -1;
int bottomPadding = -1;
int startPadding = UNDEFINED_PADDING;
int endPadding = UNDEFINED_PADDING;


...


final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;


// Set default values.
viewFlagValues |= FOCUSABLE_AUTO;
viewFlagMasks |= FOCUSABLE_AUTO;


//for迴圈迭代獲取到的n個自定義屬性值
final int N = a.getIndexCount();
for (int i = 0; i < N; i++) {
int attr = a.getIndex(i);
switch (attr) {
case com.android.internal.R.styleable.View_background:
background = a.getDrawable(attr);
break;
case com.android.internal.R.styleable.View_padding:
padding = a.getDimensionPixelSize(attr, -1);
mUserPaddingLeftInitial = padding;
mUserPaddingRightInitial = padding;
leftPaddingDefined = true;
rightPaddingDefined = true;
break;
case com.android.internal.R.styleable.View_paddingHorizontal:
paddingHorizontal = a.getDimensionPixelSize(attr, -1);
mUserPaddingLeftInitial = paddingHorizontal;
mUserPaddingRightInitial = paddingHorizontal;
leftPaddingDefined = true;
rightPaddingDefined = true;
break;
...
}
}


setOverScrollMode(overScrollMode);


// Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
// the resolved layout direction). Those cached values will be used later during padding
// resolution.
mUserPaddingStart = startPadding;
mUserPaddingEnd = endPadding;


if (background != null) {
setBackground(background);
}


...


//回收自定義屬性陣列
a.recycle();


// Needs to be called after mViewFlags is set
if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
recomputePadding();
}


if (x != 0 || y != 0) {
scrollTo(x, y);
}


if (transformSet) {
setTranslationX(tx);
setTranslationY(ty);
setTranslationZ(tz);
setElevation(elevation);
setRotation(rotation);
setRotationX(rotationX);
setRotationY(rotationY);
setScaleX(sx);
setScaleY(sy);
}


if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
setScrollContainer(true);
}


computeOpaqueFlags();
}