国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Android 初級面試者拾遺(前臺界面篇)之 View 和 ViewGroup

malakashi / 2544人閱讀

摘要:層面中可以通過方法攔截事件傳遞,返回代表同一事件列不再向下傳遞給子,返回代表事件繼續(xù)傳遞,默認(rèn)返回。同時注冊兩者事件傳遞順序,方法將會先于方法執(zhí)行,并且方法可能執(zhí)行多次事件。如此反復(fù)執(zhí)行初始化布局繪制過程容易造成性能問題。

View 和 ViewGroup

View 是 Android 中最基本的 UI 組件,在屏幕上繪制一塊矩形區(qū)域。
ViewGroup 是一種特殊的 View,它可以包含多個子 View 和子 ViewGroup,用于放置、組織、管理視圖結(jié)構(gòu)。

常用控件和布局的繼承結(jié)構(gòu):

LinearLayout 和 RelativeLayout 性能對比

Android Project 默認(rèn)生成的 avtivity_main.xml 布局文件中,根結(jié)點使用 RelativeLayout,然而作為頂級 View 的 DecorView 則是垂直方向的 LinearLayout,從上至下分為標(biāo)題欄、內(nèi)容欄。常用的 setContentView() 方法就是為內(nèi)容欄設(shè)置布局。

RelativeLayout 的子 View 需要兩次 onMeasure() 過程,而 LinearLayout 只需一次,但是當(dāng) LinearLayout 設(shè)置 weight 屬性后,同樣需要兩次 onMeasure() 過程。

在不影響層級深度的情況下,推薦使用 Linearlayout 而非 RelativeLayout。

DecorView 層級深度已知且固定,標(biāo)題欄與內(nèi)容欄,采用 RelativeLayout 并不會降低層級深度,因此使用 LinearLayout 效率更高。

Project 默認(rèn)使用 RelativeLayout 作為根結(jié)點,是希望開發(fā)者能夠盡量減少 View 層級結(jié)構(gòu),避免使用 LinearLayout 多層嵌套完成布局。

LayoutInflater

LayoutInflater inflate() 方法用于動態(tài)加載布局,將 XML 布局文件實例化為其對應(yīng)的 View 對象。

public View inflate(int resource, ViewGroup root)    // 方法一
public View inflate(int resource, ViewGroup root, boolean attachToRoot)    // 方法二
inflate() 方法參數(shù)詳解

resource(int): 需要加載的 XML 布局資源的 ID

root(ViewGroup): 設(shè)置加載的布局的父級層次結(jié)構(gòu)

attachToRoot(boolean): 是否將加載的布局附加到父級層次結(jié)構(gòu)

情況一: root 為 null;

如果 root 為 null,attachToRoot 參數(shù)將失去意義。

無需將 resource 指定的布局添加到 root 中,同時沒有任何 ViewGroup 容器來協(xié)助 resource 指定的布局的根元素生成布局參數(shù) LayoutParams。

情況二: root 不為 null,attachToRoot 為 true;

將 resource 指定的布局添加到 root 中,inflate() 方法返回結(jié)合后的 View,其根元素是 root。View 將會根據(jù)它的父 ViewGroup 容器的 LayoutParams 進(jìn)行測量和放置。

使用方法一即未設(shè)置 attachToRoot 參數(shù)時,如果 root 不為 null,attachToRoot 參數(shù)默認(rèn)為true。

情況三: root 不為 null,attachToRoot 為 false;

無需將 resource 指定的布局添加到 root 中,inflate() 方法返回 resource 指定的布局 View,根元素是自身的最外層,View 不存在父 ViewGroup,但是可以根據(jù) root 的 LayoutParams 進(jìn)行測量和放置。

情況三不解之處在于,既然 attachToRoot 為 false,無需將 resource 指定的布局添加到 root 中,那么為什么 root 仍然不為 null?創(chuàng)建的 View 必然包含 layout 屬性,但是這些屬性需要在 ViewGroup 容器中才能生效,根據(jù) ViewGroup 容器的 LayoutParams 進(jìn)行測量和放置 View。
情況三的意思是,無需將 View 添加到某個 ViewGroup 容器中,卻又能根據(jù)這個 ViewGroup 容器的 LayoutParams 進(jìn)行測量和放置 View。

情況一和情況三依賴手動添加 View。

多個參數(shù)版本的 inflate() 方法最終匯合調(diào)用:

public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)
解析 XML 格式數(shù)據(jù)

Pull 解析方式基于事件驅(qū)動方式,Android 中使用 XmlPullParser 對象,調(diào)用 setInput() 方法傳遞數(shù)據(jù)給解析器。開始循環(huán)解析,通過 getEventType()方法獲取當(dāng)前解析事件,如果當(dāng)前解析事件并非 END_DOCUMENT,調(diào)用 next() 方法獲取下一個解析事件。針對不同事件處理,getName() 方法可以獲得當(dāng)前節(jié)點名字(tag name),nextText() 方法可以獲得當(dāng)前節(jié)點內(nèi)的具體內(nèi)容(TEXT)。

Events(事件):

START_DOCUMENT 開始文檔

START_TAG 開始標(biāo)簽

TEXT 文本內(nèi)容

END_TAG 結(jié)束標(biāo)簽

END_DOCUMENT 結(jié)束文檔

XML(可擴展標(biāo)記語言)組成部分:

Declaration(聲明):XML 文件首行聲明一些文檔信息 。

Tag(標(biāo)簽):以 < 開頭,以 > 結(jié)尾。包括:start-tag(

)、end-tag(
)、empty-element tag()。

Text(文本):開始與結(jié)束 tag 之間的文本內(nèi)容。

Attribute(屬性):位于開始 tag 之中,以鍵值對形式補充說明 tag 。

視圖繪制流程

onMeasure() 決定 View 的大小

onLayout() 決定 View 在 ViewGroup 中的位置

onDraw() 繪制 View

onMeasure()

視圖大小的測量過程,是由父視圖、布局文件、以及視圖本身共同完成的。

父視圖提供參考大?。∕easureSpec: specSize, specMode)給子視圖

UNSPECIFIED 子視圖按照自身條件設(shè)置成任意的大小

EXACTLY 父視圖希望子視圖的大小應(yīng)該由 specSize 來決定

AT MOST 子視圖最大只能是 specSize 中指定的大小

布局文件中指定視圖的大小

MATCH_PARENT

WRAP_CONTENT

視圖本身最終決定大小

onLayout()

根據(jù)測量出來的(onMeasure())寬度和高度確定視圖的位置。關(guān)鍵方法:public void layout (int l, int t, int r, int b) 方法接收左、上、右、下的坐標(biāo)。

onDraw()

完成測量(onMeasure())和布局操作(onLayout())之后,創(chuàng)建 Canvas 對象繪制視圖。

事件分發(fā)機制

重要方法:

dispatchTouchEvent()

onInterceptTouchEvent()

onTouchEvent()

事件分發(fā)順序:由 Activity 開始先傳遞給 ViewGroup 再傳遞給 View。

Activity 層面

事件分發(fā)始于 Activity.dispatchTouchEvent() 方法,傳遞事件至 Window 的根視圖。

若最終沒有視圖消費事件則調(diào)用 Activity.onTouchEvent(event) 方法。

ViewGroup 層面

ViewGroup 中可以通過 ViewGroup.onInterceptTouchEvent() 方法攔截事件傳遞,返回 true 代表同一事件列不再向下傳遞給子 View,返回 false 代表事件繼續(xù)傳遞,默認(rèn)返回 false。

事件遞歸傳遞至子 View 的 View.dispatchTouchEvent() 方法,如果事件被子 View 消費,則返回 true,ViewGroup 將無法再處理事件。

如果沒有子 View 消費事件則判斷 ViewGroup 中是否存在已注冊的事件監(jiān)聽器(mOnTouchListener),存在則調(diào)用它的 ViewGroup.OnTouchListener.onTouch() 方法,如果 onTouch() 方法返回 false 即未消費事件,則進(jìn)一步去執(zhí)行 ViewGroup.onTouchEvent(event) 方法。

View 層面

View.dispatchTouchEvent() 方法:首先判斷 View 中是否存在已注冊的事件監(jiān)聽器(mOnTouchListener),存在則調(diào)用它的 View.OnTouchListener.onTouch() 方法,如若 onTouch() 方法返回 false 即未消費事件,則進(jìn)一步去執(zhí)行 View.onTouchEvent(event) 方法。

View 可以注冊事件監(jiān)聽器(Listener)實現(xiàn) onClick(View v)、onTouch(View v, MotionEvent event) 方法。相比 onClick() 方法,onTouch() 方法能夠做的事情更多,判斷手指按下、抬起、移動等事件。同時注冊兩者事件傳遞順序,onTouch() 方法將會先于 onClick() 方法執(zhí)行,并且 onTouch() 方法可能執(zhí)行多次(MotionEvent 事件:ACTION_DOWNACTION_UPACTION_MOVE)。如若設(shè)置 onTouch() 方法返回值為 true,事件視為被 onTouch() 方法消費,不再繼續(xù)向下傳遞給 onClick() 方法。

布局性能優(yōu)化

優(yōu)化布局層級

每個控件和布局都需要經(jīng)過初始化、布局、繪制過程才能呈現(xiàn)出來。當(dāng)使用多層嵌套的 LinearLayout 以致產(chǎn)生較深的視圖層級結(jié)構(gòu),更甚者在 LinearLayout 中使用 layout_weight 參數(shù),導(dǎo)致子 View 需要兩次 onMeasure() 過程。如此反復(fù)執(zhí)行初始化、布局、繪制過程容易造成性能問題。

需要開發(fā)者檢查布局、修正布局,可以借助 Lint 工具發(fā)現(xiàn)布局文件中的視圖層級結(jié)構(gòu)里值得優(yōu)化的地方,同時扁平化處理原本多層嵌套的布局,例如使用 RelativeLayout 作為根節(jié)點。

使用 復(fù)用布局

通過使用 標(biāo)簽,在當(dāng)前布局中嵌入另一個較大的布局作為組件,從而復(fù)用完整的布局的視圖層級結(jié)構(gòu)。

標(biāo)簽的區(qū)別:

標(biāo)簽旨在重用布局文件

layout1.xml:


   

layout2.xml:


   

最終布局視圖層級結(jié)構(gòu):


   
      
   

標(biāo)簽旨在減少視圖層級

layout2.xml:


   

最終布局視圖層級結(jié)構(gòu):


   

懶加載 View

有時布局中包含很少使用的復(fù)雜視圖,可以在需要時加載視圖,減少內(nèi)存使用,加快渲染速度。ViewStub 是一個輕量級視圖,在構(gòu)建視圖層級結(jié)構(gòu)中消耗資源較小。但是實際項目使用中,開發(fā)者習(xí)慣切換視圖的 Visibility 而不是使用 ViewStub。

屏幕大小適配手段

使用 wrap_contentmatch_parent,布局盡可能自適應(yīng)屏幕大小。

wrap_content 讓當(dāng)前控件的大小能夠剛好包含住里面的內(nèi)容。

match_parent 讓當(dāng)前控件的大小和父布局的大小一樣。

使用配置限定符,程序在運行時根據(jù)當(dāng)前設(shè)備的配置自動加載合適的資源。

Android 常見的限定符:

屏幕特征 限定符
大小 small, normal, large, xlarge
分辨率 ldpi, mdpi, hdpi, xhdpi, xxhdpi
方向 land, port

使用 Nine-Patch 圖片 ,從圖片資源角度,支持不同屏幕大小,Nine-Patch 圖片允許指定哪些區(qū)域可以拉伸而哪些區(qū)域不可以。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/72021.html

相關(guān)文章

  • Android 初級面試拾遺前臺界面 View ViewGroup

    摘要:層面中可以通過方法攔截事件傳遞,返回代表同一事件列不再向下傳遞給子,返回代表事件繼續(xù)傳遞,默認(rèn)返回。同時注冊兩者事件傳遞順序,方法將會先于方法執(zhí)行,并且方法可能執(zhí)行多次事件。如此反復(fù)執(zhí)行初始化布局繪制過程容易造成性能問題。 View 和 ViewGroup View 是 Android 中最基本的 UI 組件,在屏幕上繪制一塊矩形區(qū)域。 ViewGroup 是一種特殊的 View,它...

    Juven 評論0 收藏0
  • Android 初級面試拾遺前臺界面 ListView RecyclerView

    摘要:方法根據(jù)子項所處的位置判斷具體類型并返回。調(diào)用方法解除子項與之間的關(guān)聯(lián)。自定義適配器適配器繼承自,并將泛型指定為內(nèi)部類。使用支持多種布局方式借助能夠靈活地將列表控件放入不同的容器。 ListView 和 RecyclerView 最常用和最難用的控件 由于手機屏幕空間有限,無法顯示全部內(nèi)容。當(dāng)有大量數(shù)據(jù)需要展示的時候,借助列表控件。通過手指上下滑動,使得屏幕內(nèi)外的數(shù)據(jù)不斷進(jìn)出。 最基本...

    MartinDai 評論0 收藏0

發(fā)表評論

0條評論

malakashi

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<