亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android源碼學習之組合模式定義及應用

2020-04-11 12:36:43
字體:
來源:轉載
供稿:網友

組合模式定義

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

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

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

1. Component抽象組件。定義參加組合對象的共有方法和屬性,可以定義一些默認的函數或屬性。

2. Leaf葉子節點。構成組合樹的最小構建單元。

3. Composite樹枝節點組件。它的作用是組合樹枝節點和葉子節點形成一個樹形結構。

高層模塊調用簡單。一棵樹形結構的所有節點都是Component,局部和整體對調用者來說都是一樣的,沒有區別,所以高層模塊不比關心自己處理的是單個對象還是整個組合結構,簡化了高層模塊的代碼。

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

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

在Android源碼中,都能找到使用組合模式的例子,其中在《Android源碼學習之觀察者模式應用》介紹到的ViewGroup和View的結構就是一個組合模式,結構圖如下所示:

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

復制代碼 代碼如下:

* @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 {

接著看增加孩子節點函數
復制代碼 代碼如下:

/**
* 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()方法,有了增加孩子節點,肯定有相對應刪除孩子節點的方法,接著看:

復制代碼 代碼如下:


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);
}


同樣的,也有查找獲得孩子節點的函數:
復制代碼 代碼如下:

/**
* 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];
}

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

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

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

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);
}
}
...

最后送上“基本控件繼承關系圖”:

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美成人性生活| 亚州国产精品久久久| 久久久久久久久久久亚洲| 日韩的一区二区| 亲爱的老师9免费观看全集电视剧| 美女啪啪无遮挡免费久久网站| 亚洲热线99精品视频| 韩国国内大量揄拍精品视频| 91国产中文字幕| 精品女同一区二区三区在线播放| 久久久久日韩精品久久久男男| 国产乱肥老妇国产一区二| 九九精品在线视频| 欧美第一黄网免费网站| 久久国产精品免费视频| 欧美成年人在线观看| 伊人亚洲福利一区二区三区| 国产一区二区三区在线观看网站| 亚洲一区二区三区在线免费观看| 亚洲成人动漫在线播放| 久久久久一本一区二区青青蜜月| 亚洲一区亚洲二区亚洲三区| 欧美伦理91i| 精品高清一区二区三区| 精品无人区太爽高潮在线播放| 国产欧美 在线欧美| 精品久久久久久久久久久久久久| 国产精品久久久久久影视| www.久久久久| 97香蕉久久夜色精品国产| 自拍偷拍亚洲欧美| 亚洲欧美中文日韩v在线观看| 97在线观看视频| 疯狂做受xxxx欧美肥白少妇| 亚洲码在线观看| 久久人人看视频| 中文字幕日韩欧美在线| 日韩成人高清在线| 国产午夜精品一区二区三区| 青草青草久热精品视频在线观看| 日韩国产精品视频| 国产精品亚洲аv天堂网| 欧美日韩性视频在线| 欧美日韩中文在线| 欧美成人精品不卡视频在线观看| 九色91av视频| 亚洲综合自拍一区| 欧美亚洲视频在线看网址| 国产精品永久在线| 奇米成人av国产一区二区三区| 国产美女直播视频一区| 黑人巨大精品欧美一区免费视频| 国产成人免费91av在线| 亚洲白拍色综合图区| 久久久久久久久国产| 欧美人交a欧美精品| 亚洲视频在线观看免费| 亚洲国产精品久久久久秋霞蜜臀| 国产精品视频午夜| 在线亚洲欧美视频| 青青草原一区二区| 日韩综合视频在线观看| 精品美女久久久久久免费| 欧美日韩在线视频首页| 高清欧美电影在线| 国产在线观看一区二区三区| 欧美有码在线观看| 久久精品国产久精国产一老狼| 欧美日韩国产成人| 成人免费xxxxx在线观看| 国产精品久久久久久久久借妻| 国产精品91在线观看| 国产乱肥老妇国产一区二| 日韩极品精品视频免费观看| 国产一区二区三区在线视频| 久久久999精品视频| 色噜噜久久综合伊人一本| 久久成人人人人精品欧| 国产在线精品自拍| 亚洲国产成人久久| 九九热这里只有精品免费看| 在线视频日本亚洲性| 欧美精品在线观看91| 精品久久久91| 欧美中文在线免费| 欧美激情在线一区| 亚洲精品第一国产综合精品| 欧美另类极品videosbestfree| 日韩av电影国产| 精品人伦一区二区三区蜜桃免费| 91色在线视频| 国产一区二区三区毛片| 亚洲va久久久噜噜噜久久天堂| 久热精品视频在线观看一区| 久久久久九九九九| 97超视频免费观看| 亚洲影视九九影院在线观看| 亚洲国产欧美一区二区三区久久| 欧美日韩中文在线| 国产亚洲精品久久久久久| 国产精品18久久久久久麻辣| 亚洲精品视频播放| 欧美性猛交xxxx乱大交极品| 日韩精品极品视频免费观看| 日韩美女视频在线观看| 欧美一区二三区| 亚洲国产福利在线| 91欧美精品午夜性色福利在线| 国产日韩视频在线观看| 国产精品狼人色视频一区| 日韩激情在线视频| 国产精品日日摸夜夜添夜夜av| 91麻豆国产精品| 热re91久久精品国99热蜜臀| 91久久久精品| 国产亚洲精品激情久久| 久久久精品久久久久| 51精品在线观看| 国产精品久久久久久久久男| 欧美高清自拍一区| 日韩高清不卡av| 色综合老司机第九色激情| 国产精品亚洲美女av网站| 国产美女91呻吟求| 日韩精品一区二区视频| 国产精品白丝jk喷水视频一区| 国内精品视频在线| 日韩美女视频免费看| 日韩av在线精品| 在线视频国产日韩| 久久99国产精品久久久久久久久| 最近2019年日本中文免费字幕| 日韩在线观看成人| 精品国产区一区二区三区在线观看| 久久综合伊人77777| 国产精品天天狠天天看| 欧美激情videoshd| 美女久久久久久久| 91精品久久久久久久久| 日本欧美精品在线| 亚洲精品美女久久久久| 久久久国产91| 欧美精品18videos性欧美| 亚洲欧美中文日韩在线v日本| 欧美—级高清免费播放| 精品国产欧美一区二区三区成人| 海角国产乱辈乱精品视频| 亚洲国产精品高清久久久| 欧美成年人视频网站欧美| 国产性猛交xxxx免费看久久| 国产亚洲综合久久| 理论片在线不卡免费观看| 8x海外华人永久免费日韩内陆视频| 亚洲精品www久久久久久广东| 亚洲福利视频二区| 国产精品成人av在线| 欧美床上激情在线观看| 性欧美在线看片a免费观看| 欧美日韩国内自拍| 欧美色道久久88综合亚洲精品| 国产高清在线不卡| 国产精品久久97| 国产欧亚日韩视频| 日韩高清电影免费观看完整版|