最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android源碼學(xué)習(xí)之組合模式定義及應(yīng)用

 更新時間:2013年01月06日 12:09:41   作者:  
將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu),使得用戶對單個對象和組合對象的使用具有一致性,需要了解的朋友可以參考下

組合模式定義

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu),使得用戶對單個對象和組合對象的使用具有一致性。

如上圖所示(截取自《Head First Design Patterns》一書),主要包括三個部分

1. Component抽象組件。定義參加組合對象的共有方法和屬性,可以定義一些默認(rèn)的函數(shù)或?qū)傩浴?/P>

2. Leaf葉子節(jié)點。構(gòu)成組合樹的最小構(gòu)建單元。

3. Composite樹枝節(jié)點組件。它的作用是組合樹枝節(jié)點和葉子節(jié)點形成一個樹形結(jié)構(gòu)。

高層模塊調(diào)用簡單。一棵樹形結(jié)構(gòu)的所有節(jié)點都是Component,局部和整體對調(diào)用者來說都是一樣的,沒有區(qū)別,所以高層模塊不比關(guān)心自己處理的是單個對象還是整個組合結(jié)構(gòu),簡化了高層模塊的代碼。

節(jié)點自由擴展增加。使用組合模式,如果想增加一個樹枝節(jié)點或者葉子節(jié)點都是很簡單的,只要找到它的父節(jié)點就可以了,非常容易擴展,符合“開閉原則”。

應(yīng)用最廣的模式之一。應(yīng)用在維護和展示部分-整體關(guān)系的場景,如樹形菜單、文件夾管理等等。

在Android源碼中,都能找到使用組合模式的例子,其中在《Android源碼學(xué)習(xí)之觀察者模式應(yīng)用》介紹到的ViewGroup和View的結(jié)構(gòu)就是一個組合模式,結(jié)構(gòu)圖如下所示:

現(xiàn)在來看看它們是如何利用組合模式組織在一起的,首先在View類定義了有關(guān)具體操作,然后在ViewGroup類中繼承View類,并添加相關(guān)的增加、刪除和查找孩子View節(jié)點,代碼如下:

復(fù)制代碼 代碼如下:

* @attr ref android.R.styleable#ViewGroup_clipChildren
* @attr ref android.R.styleable#ViewGroup_clipToPadding
* @attr ref android.R.styleable#ViewGroup_layoutAnimation
* @attr ref android.R.styleable#ViewGroup_animationCache
* @attr ref android.R.styleable#ViewGroup_persistentDrawingCache
* @attr ref android.R.styleable#ViewGroup_alwaysDrawnWithCache
* @attr ref android.R.styleable#ViewGroup_addStatesFromChildren
* @attr ref android.R.styleable#ViewGroup_descendantFocusability
* @attr ref android.R.styleable#ViewGroup_animateLayoutChanges
*/
public abstract class ViewGroup extends View implements ViewParent, ViewManager {

接著看增加孩子節(jié)點函數(shù)
復(fù)制代碼 代碼如下:

/**
* Adds a child view. If no layout parameters are already set on the child, the
* default parameters for this ViewGroup are set on the child.
*
* @param child the child view to add
*
* @see #generateDefaultLayoutParams()
*/
public void addView(View child) {
addView(child, -1);
}

/**
* Adds a child view. If no layout parameters are already set on the child, the
* default parameters for this ViewGroup are set on the child.
*
* @param child the child view to add
* @param index the position at which to add the child
*
* @see #generateDefaultLayoutParams()
*/
public void addView(View child, int index) {
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = generateDefaultLayoutParams();
if (params == null) {
throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
}
}
addView(child, index, params);
}

/**
* Adds a child view with this ViewGroup's default layout parameters and the
* specified width and height.
*
* @param child the child view to add
*/
public void addView(View child, int width, int height) {
final LayoutParams params = generateDefaultLayoutParams();
params.width = width;
params.height = height;
addView(child, -1, params);
}

/**
* Adds a child view with the specified layout parameters.
*
* @param child the child view to add
* @param params the layout parameters to set on the child
*/
public void addView(View child, LayoutParams params) {
addView(child, -1, params);
}

/**
* Adds a child view with the specified layout parameters.
*
* @param child the child view to add
* @param index the position at which to add the child
* @param params the layout parameters to set on the child
*/
public void addView(View child, int index, LayoutParams params) {
if (DBG) {
System.out.println(this + " addView");
}

// addViewInner() will call child.requestLayout() when setting the new LayoutParams
// therefore, we call requestLayout() on ourselves before, so that the child's request
// will be blocked at our level
requestLayout();
invalidate(true);
addViewInner(child, index, params, false);
}

在ViewGroup中我們找到了添加addView()方法,有了增加孩子節(jié)點,肯定有相對應(yīng)刪除孩子節(jié)點的方法,接著看:

復(fù)制代碼 代碼如下:


public void removeView(View view) {
removeViewInternal(view);
requestLayout();
invalidate(true);
}

/**
* Removes a view during layout. This is useful if in your onLayout() method,
* you need to remove more views.
*
* @param view the view to remove from the group
*/
public void removeViewInLayout(View view) {
removeViewInternal(view);
}

/**
* Removes a range of views during layout. This is useful if in your onLayout() method,
* you need to remove more views.
*
* @param start the index of the first view to remove from the group
* @param count the number of views to remove from the group
*/
public void removeViewsInLayout(int start, int count) {
removeViewsInternal(start, count);
}

/**
* Removes the view at the specified position in the group.
*
* @param index the position in the group of the view to remove
*/
public void removeViewAt(int index) {
removeViewInternal(index, getChildAt(index));
requestLayout();
invalidate(true);
}

/**
* Removes the specified range of views from the group.
*
* @param start the first position in the group of the range of views to remove
* @param count the number of views to remove
*/
public void removeViews(int start, int count) {
removeViewsInternal(start, count);
requestLayout();
invalidate(true);
}

private void removeViewInternal(View view) {
final int index = indexOfChild(view);
if (index >= 0) {
removeViewInternal(index, view);
}
}

private void removeViewInternal(int index, View view) {

if (mTransition != null) {
mTransition.removeChild(this, view);
}

boolean clearChildFocus = false;
if (view == mFocused) {
view.clearFocusForRemoval();
clearChildFocus = true;
}

if (view.getAnimation() != null ||
(mTransitioningViews != null && mTransitioningViews.contains(view))) {
addDisappearingView(view);
} else if (view.mAttachInfo != null) {
view.dispatchDetachedFromWindow();
}

onViewRemoved(view);

needGlobalAttributesUpdate(false);

removeFromArray(index);

if (clearChildFocus) {
clearChildFocus(view);
}
}

/**
* Sets the LayoutTransition object for this ViewGroup. If the LayoutTransition object is
* not null, changes in layout which occur because of children being added to or removed from
* the ViewGroup will be animated according to the animations defined in that LayoutTransition
* object. By default, the transition object is null (so layout changes are not animated).
*
* @param transition The LayoutTransition object that will animated changes in layout. A value
* of <code>null</code> means no transition will run on layout changes.
* @attr ref android.R.styleable#ViewGroup_animateLayoutChanges
*/
public void setLayoutTransition(LayoutTransition transition) {
if (mTransition != null) {
mTransition.removeTransitionListener(mLayoutTransitionListener);
}
mTransition = transition;
if (mTransition != null) {
mTransition.addTransitionListener(mLayoutTransitionListener);
}
}

/**
* Gets the LayoutTransition object for this ViewGroup. If the LayoutTransition object is
* not null, changes in layout which occur because of children being added to or removed from
* the ViewGroup will be animated according to the animations defined in that LayoutTransition
* object. By default, the transition object is null (so layout changes are not animated).
*
* @return LayoutTranstion The LayoutTransition object that will animated changes in layout.
* A value of <code>null</code> means no transition will run on layout changes.
*/
public LayoutTransition getLayoutTransition() {
return mTransition;
}

private void removeViewsInternal(int start, int count) {
final View focused = mFocused;
final boolean detach = mAttachInfo != null;
View clearChildFocus = null;

final View[] children = mChildren;
final int end = start + count;

for (int i = start; i < end; i++) {
final View view = children[i];

if (mTransition != null) {
mTransition.removeChild(this, view);
}

if (view == focused) {
view.clearFocusForRemoval();
clearChildFocus = view;
}

if (view.getAnimation() != null ||
(mTransitioningViews != null && mTransitioningViews.contains(view))) {
addDisappearingView(view);
} else if (detach) {
view.dispatchDetachedFromWindow();
}

needGlobalAttributesUpdate(false);

onViewRemoved(view);
}

removeFromArray(start, count);

if (clearChildFocus != null) {
clearChildFocus(clearChildFocus);
}
}

/**
* Call this method to remove all child views from the
* ViewGroup.
*/
public void removeAllViews() {
removeAllViewsInLayout();
requestLayout();
invalidate(true);
}

/**
* Called by a ViewGroup subclass to remove child views from itself,
* when it must first know its size on screen before it can calculate how many
* child views it will render. An example is a Gallery or a ListView, which
* may "have" 50 children, but actually only render the number of children
* that can currently fit inside the object on screen. Do not call
* this method unless you are extending ViewGroup and understand the
* view measuring and layout pipeline.
*/
public void removeAllViewsInLayout() {
final int count = mChildrenCount;
if (count <= 0) {
return;
}

final View[] children = mChildren;
mChildrenCount = 0;

final View focused = mFocused;
final boolean detach = mAttachInfo != null;
View clearChildFocus = null;
needGlobalAttributesUpdate(false);

for (int i = count - 1; i >= 0; i--) {
final View view = children[i];

if (mTransition != null) {
mTransition.removeChild(this, view);
}

if (view == focused) {
view.clearFocusForRemoval();
clearChildFocus = view;
}

if (view.getAnimation() != null ||
(mTransitioningViews != null && mTransitioningViews.contains(view))) {
addDisappearingView(view);
} else if (detach) {
view.dispatchDetachedFromWindow();
}

onViewRemoved(view);

view.mParent = null;
children[i] = null;
}

if (clearChildFocus != null) {
clearChildFocus(clearChildFocus);
}
}

/**
* Finishes the removal of a detached view. This method will dispatch the detached from
* window event and notify the hierarchy change listener.
*
* @param child the child to be definitely removed from the view hierarchy
* @param animate if true and the view has an animation, the view is placed in the
* disappearing views list, otherwise, it is detached from the window
*
* @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)
* @see #detachAllViewsFromParent()
* @see #detachViewFromParent(View)
* @see #detachViewFromParent(int)
*/
protected void removeDetachedView(View child, boolean animate) {
if (mTransition != null) {
mTransition.removeChild(this, child);
}

if (child == mFocused) {
child.clearFocus();
}

if ((animate && child.getAnimation() != null) ||
(mTransitioningViews != null && mTransitioningViews.contains(child))) {
addDisappearingView(child);
} else if (child.mAttachInfo != null) {
child.dispatchDetachedFromWindow();
}

onViewRemoved(child);
}


同樣的,也有查找獲得孩子節(jié)點的函數(shù):
復(fù)制代碼 代碼如下:

/**
* Returns the view at the specified position in the group.
*
* @param index the position at which to get the view from
* @return the view at the specified position or null if the position
* does not exist within the group
*/
public View getChildAt(int index) {
if (index < 0 || index >= mChildrenCount) {
return null;
}
return mChildren[index];
}

:其中具體葉子節(jié)點,如Button,它是繼承TextView的,TextView是繼承View的,代碼如下:
復(fù)制代碼 代碼如下:

public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
。。。
}

:其中使用(繼承)到ViewGroup類的有我們常用的容器類(包裝和容納各種View),如LinearLayout、FrameLayout等,代碼如下:
復(fù)制代碼 代碼如下:

public class LinearLayout extends ViewGroup {
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
。。。
}

public class FrameLayout extends ViewGroup {
...
}

public class RelativeLayout extends ViewGroup {
private static final String LOG_TAG = "RelativeLayout";

private static final boolean DEBUG_GRAPH = false;
...
}

public class AbsoluteLayout extends ViewGroup {
public AbsoluteLayout(Context context) {
super(context);
}
}
...

最后送上“基本控件繼承關(guān)系圖”:

本人能力有限,寫的很粗糙,恭候大家的批評指正,謝謝~~~

相關(guān)文章

  • Android10?Binder原理概述深入解析

    Android10?Binder原理概述深入解析

    這篇文章主要為大家介紹了Android10?Binder原理概述深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • Framework源碼面試之a(chǎn)ctivity啟動流程

    Framework源碼面試之a(chǎn)ctivity啟動流程

    這篇文章主要為大家介紹了Framework源碼面試之a(chǎn)ctivity啟動流程實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • Android NoSuchFieldError解決辦法

    Android NoSuchFieldError解決辦法

    這篇文章主要介紹了Android NoSuchFieldError解決辦法的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-10-10
  • Android超詳細(xì)介紹自定義多選框與點擊按鈕跳轉(zhuǎn)界面的實現(xiàn)

    Android超詳細(xì)介紹自定義多選框與點擊按鈕跳轉(zhuǎn)界面的實現(xiàn)

    這篇文章主要介紹了在Android開發(fā)中如何來實現(xiàn)自定義多選框以及如何實現(xiàn)點擊按鈕跳轉(zhuǎn)界面的功能,感興趣的朋友快來看看吧
    2022-03-03
  • Android仿QQ個人標(biāo)簽添加與刪除功能

    Android仿QQ個人標(biāo)簽添加與刪除功能

    這篇文章主要為大家詳細(xì)介紹了Android仿QQ個人標(biāo)簽添加與刪除功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • Android擴大View點擊范圍的方法

    Android擴大View點擊范圍的方法

    Android4.0設(shè)計規(guī)定的有效可觸摸的UI元素標(biāo)準(zhǔn)是48dp,轉(zhuǎn)化為一個物理尺寸約為9毫米。7~10毫米,這是一個用戶手指能準(zhǔn)確并且舒適觸摸的區(qū)域。本文將介紹Android擴大View點擊范圍的方法
    2021-05-05
  • Android開發(fā)新手必須知道的10大嚴(yán)重錯誤

    Android開發(fā)新手必須知道的10大嚴(yán)重錯誤

    這篇文章主要介紹了Android開發(fā)新手必須知道的10大嚴(yán)重錯誤,總結(jié)分析了Android開發(fā)中幫助文件、開發(fā)工具、社區(qū)等的重要性以及重要的開發(fā)原則,需要的朋友可以參考下
    2016-01-01
  • Android中Fragment 真正的完全解析(上)

    Android中Fragment 真正的完全解析(上)

    本篇文章主要介紹了Android中Fragment完全解析,具有一定的參考價值,有需要的可以了解一下。
    2016-11-11
  • Android Mms之:深入理解Compose

    Android Mms之:深入理解Compose

    本篇文章是對Compose進行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • Android自定義Toast之WindowManager

    Android自定義Toast之WindowManager

    這篇文章主要為大家詳細(xì)介紹了Android自定義Toast之WindowManager的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08

最新評論

沁源县| 沙雅县| 安龙县| 伊金霍洛旗| 溆浦县| 黎川县| 德保县| 桑日县| 平利县| 耒阳市| 长沙市| 德州市| 宜春市| 四平市| 沐川县| 渑池县| 桦南县| 洛川县| 垣曲县| 萨嘎县| 大埔区| 宁都县| 蒙自县| 长武县| 通化市| 涟源市| 新乡县| 渭源县| 禄丰县| 奎屯市| 嘉祥县| 镇江市| 潮州市| 水富县| 定襄县| 淅川县| 洪湖市| 施秉县| 浦北县| 钦州市| 留坝县|