偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

【專家專欄】Android 4.0 Launcher源碼分析系列(二)

原創(chuàng)
移動(dòng)開(kāi)發(fā) Android
本文為筆名“傻蛋”的51CTO特約專家的《Android 4.0 Launcher源碼分析系列》專欄的第二篇,這一節(jié)傻蛋將從整個(gè)Laucher的入口點(diǎn)入手,同時(shí)Laucher在加載了它的布局文件Laucher.xml時(shí)都干了些什么。

【51CTO.com 2月2日獨(dú)家特稿】上一節(jié)我們研究了Launcher的整體結(jié)構(gòu),這一節(jié)我們看看整個(gè)Laucher的入口點(diǎn),同時(shí)Laucher在加載了它的布局文件Laucher.xml時(shí)都干了些什么。

我們?cè)谠创a中可以找到LauncherApplication, 它繼承了Application類,當(dāng)整個(gè)Launcher啟動(dòng)時(shí),它就是整個(gè)程序的入口。我們先來(lái)看它們?cè)贏ndroidManifest.xml中是怎么配置的。

  1. <application 
  2.     android:name="com.android.launcher2.LauncherApplication" 
  3.     android:label="@string/application_name" 
  4.     android:icon="@drawable/ic_launcher_home" 
  5.     android:hardwareAccelerated="@bool/config_hardwareAccelerated" 
  6.     android:largeHeap="@bool/config_largeHeap">     

首先通過(guò)android:name指定了整個(gè)Launcher的Application也就是入口是在 com.android.launcher2.LauncherApplication這個(gè)路徑下,android:lable指定了桌面的名字是叫 Launcher,如果要改名字就改values文件夾的string.xml中的相應(yīng)屬性就可以了。android:icon指定了Laucher的圖標(biāo),這個(gè)圖標(biāo)可以在應(yīng)用程序管理器中看見(jiàn),如下圖所示,是個(gè)可愛(ài)機(jī)器人住在一個(gè)小房子里面,如果需要更改Laucher的圖片,重新設(shè)置這個(gè)屬性就可以了。

[[56626]]

android:hardwareAccelerated="@bool/config_hardwareAccelerated" 指定了整個(gè)應(yīng)用程序是啟用硬件加速的,這樣整個(gè)應(yīng)用程序的運(yùn)行速度會(huì)更快。

android:largeHeap="@bool/config_largeHeap" 指定了應(yīng)用程序使用了大的堆內(nèi)存,能在一定程度上避免,對(duì)內(nèi)存out of memory錯(cuò)誤的出現(xiàn)。我們可以在values文件夾的config.xml中看到對(duì)是否啟用硬件加速和大內(nèi)存的配置。如下所示:

  1. <bool name="config_hardwareAccelerated">true</bool> 
  2. <bool name="config_largeHeap">false</bool> 

在Application中onCreate()方法通過(guò):sIsScreenLarge = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE || screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE; 和sScreenDensity = getResources().getDisplayMetrics().density;來(lái)判斷是否是大屏幕,同時(shí)得到它的屏幕密度。同時(shí)通過(guò)mIconCache = new IconCache(this); 來(lái)設(shè)置了應(yīng)用程序的圖標(biāo)的cache,然后申明了LauncherModel,mModel = new LauncherModel(this, mIconCache); LauncherModel主要用于加載桌面的圖標(biāo)、插件和文件夾,同時(shí)LaucherModel是一個(gè)廣播接收器,在程序包發(fā)生改變、區(qū)域、或者配置文件發(fā)生改變時(shí),都會(huì)發(fā)送廣播給LaucherModel,LaucherModel會(huì)根據(jù)不同的廣播來(lái)做相應(yīng)加載操作,此部分會(huì)在后面做詳細(xì)介紹。

在LauncherApplication完成初始化工作之后,我們就來(lái)到了Launcher.java的onCreate()方法,同樣是啟動(dòng)桌面時(shí)的一系列初始化工作。

首先需要注意的是在加載launcher布局文件時(shí)的一個(gè)TraceView的調(diào)試方法,它能夠?qū)υ谒麄冎g的方法進(jìn)行圖形化的性能分析,并且能夠具體到method 代碼如下:

  1. if (PROFILE_STARTUP) {  
  2.      android.os.Debug.startMethodTracing(  
  3.              Environment.getDataDirectory() + "/data/com.android.launcher/launcher");  
  4.  }  
  5.  if (PROFILE_STARTUP) {  
  6.      android.os.Debug.stopMethodTracing();  
  7.  }  

我指定的生成性能分析的路徑是:/data/data/com.android.launcher/launcher,啟動(dòng)launcher后我們會(huì)發(fā)現(xiàn)在指定的目錄下生成了launcher.trace文件,如下圖所示:

啟動(dòng)launcher后我們會(huì)發(fā)現(xiàn)在指定的目錄下生成了launcher.trace文件

把launcher.trace文件通過(guò)DDMS pull到電腦上,在SDK的tools目錄里,執(zhí)行traceview工具來(lái)打開(kāi)launcher.trace .如下圖所示:

把launcher.trace文件通過(guò)DDMS pull到電腦上

點(diǎn)擊查看大圖

可以看到setContentView使用了448.623ms,占整個(gè)跟蹤代碼時(shí)間的62%,所以說(shuō)在加載布局文件時(shí),肯定經(jīng)過(guò)了一系列的加載運(yùn)算,我們接著分析。

當(dāng)加載launcher布局文件的過(guò)程時(shí),最為關(guān)鍵的時(shí)對(duì)整個(gè)workspace的加載,workspace是一個(gè)自定義組件,它的繼承關(guān)系如下所示,可以看到Workspace實(shí)際上也是一個(gè)ViewGroup,可以加入其他控件。

剪切板

當(dāng)ViewGroup組件進(jìn)行加載的時(shí)候首先會(huì)讀取本控件對(duì)應(yīng)的XML文件,然后Framework層會(huì)執(zhí)行它的onMeasure()方法,根據(jù)它所包含的子控件大小來(lái)計(jì)算出整個(gè)控件要在屏幕上占的大小。Workspace重寫(xiě)了ViewGroup的onMeasure方法(在PagedView中),在workspace中是對(duì)5個(gè)子CellLayout進(jìn)行測(cè)量,的方法如下, 具體含義請(qǐng)看注釋:

  1. @Override 
  2.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
  3.         if (!mIsDataReady) { 
  4.             super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
  5.             return; 
  6.         } 
  7.         //得到寬度的模式(在配置文件中對(duì)應(yīng)的是match_parent 或者 wrap_content)和其大小 
  8.         final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 
  9.         final int widthSize = MeasureSpec.getSize(widthMeasureSpec); 
  10.         //寬度必須是match_parent,否則會(huì)拋出異常。 
  11.         if (widthMode != MeasureSpec.EXACTLY) { 
  12.             throw new IllegalStateException("Workspace can only be used in EXACTLY mode."); 
  13.         } 
  14.  
  15.         /* Allow the height to be set as WRAP_CONTENT. This allows the particular case 
  16.          * of the All apps view on XLarge displays to not take up more space then it needs. Width 
  17.          * is still not allowed to be set as WRAP_CONTENT since many parts of the code expect 
  18.          * each page to have the same width. 
  19.          */ 
  20.         //高度允許是wrap_content,因?yàn)樵诖笃聊坏那闆r下,會(huì)占了多余的位置 
  21.         final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 
  22.         int heightSize = MeasureSpec.getSize(heightMeasureSpec); 
  23.         int maxChildHeight = 0
  24.         //得到在豎值方向上和水平方向上的Padding  
  25.         final int verticalPadding = mPaddingTop + mPaddingBottom; 
  26.         final int horizontalPadding = mPaddingLeft + mPaddingRight; 
  27.  
  28.  
  29.         // The children are given the same width and height as the workspace 
  30.         // unless they were set to WRAP_CONTENT 
  31.         if (DEBUG) Log.d(TAG, "PagedView.onMeasure(): " + widthSize + ", " + heightSize  + " mPaddingTop="+mPaddingTop + " mPaddingBottom="+mPaddingBottom); 
  32.         final int childCount = getChildCount(); 
  33.         //對(duì)workspace的子View進(jìn)行遍歷,從而對(duì)它的幾個(gè)子view進(jìn)行測(cè)量。 
  34.         for (int i = 0; i < childCount; i++) { 
  35.             // disallowing padding in paged view (just pass 0) 
  36.             final View child = getPageAt(i); 
  37.             final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 
  38.  
  39.             int childWidthMode; 
  40.             if (lp.width == LayoutParams.WRAP_CONTENT) { 
  41.                 childWidthMode = MeasureSpec.AT_MOST; 
  42.             } else { 
  43.                 childWidthMode = MeasureSpec.EXACTLY; 
  44.             } 
  45.  
  46.             int childHeightMode; 
  47.             if (lp.height == LayoutParams.WRAP_CONTENT) { 
  48.                 childHeightMode = MeasureSpec.AT_MOST; 
  49.             } else { 
  50.                 childHeightMode = MeasureSpec.EXACTLY; 
  51.             } 
  52.  
  53.             final int childWidthMeasureSpec = 
  54.                 MeasureSpec.makeMeasureSpec(widthSize - horizontalPadding, childWidthMode); 
  55.             final int childHeightMeasureSpec = 
  56.                 MeasureSpec.makeMeasureSpec(heightSize - verticalPadding, childHeightMode); 
  57.             //對(duì)子View的大小進(jìn)行設(shè)置,傳入width和height參數(shù) 
  58.             child.measure(childWidthMeasureSpec, childHeightMeasureSpec); 
  59.             maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight()); 
  60.             if (DEBUG) Log.d(TAG, "\tmeasure-child" + i + ": " + child.getMeasuredWidth() + ", " 
  61.                     + child.getMeasuredHeight()); 
  62.         } 
  63.  
  64.         if (heightMode == MeasureSpec.AT_MOST) { 
  65.             heightSize = maxChildHeight + verticalPadding; 
  66.         } 
  67.         //存儲(chǔ)測(cè)量后的寬度和高度 
  68.         setMeasuredDimension(widthSize, heightSize); 
  69.  
  70.         // We can't call getChildOffset/getRelativeChildOffset until we set the measured dimensions. 
  71.         // We also wait until we set the measured dimensions before flushing the cache as well, to 
  72.         // ensure that the cache is filled with good values. 
  73.         invalidateCachedOffsets(); 
  74.         updateScrollingIndicatorPosition(); 
  75.  
  76.         if (childCount > 0) { 
  77.             mMaxScrollX = getChildOffset(childCount - 1) - getRelativeChildOffset(childCount - 1); 
  78.         } else { 
  79.             mMaxScrollX = 0
  80.         } 
  81.     } 

 

測(cè)量完畢之后就可以對(duì)子控件進(jìn)行布局了,這時(shí)候Framework層會(huì)調(diào)用PagedView中重寫(xiě)的onLayout方法。

  1. @Override 
  2.    protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 
  3.        if (!mIsDataReady) { 
  4.            return; 
  5.        } 
  6.  
  7.        if (DEBUG) Log.d(TAG, "PagedView.onLayout()"); 
  8.        //豎值方向的Padding 
  9.        final int verticalPadding = mPaddingTop + mPaddingBottom; 
  10.        final int childCount = getChildCount(); 
  11.        int childLeft = 0
  12.        if (childCount > 0) { 
  13.            if (DEBUG) Log.d(TAG, "getRelativeChildOffset(): " + getMeasuredWidth() + ", " 
  14.                    + getChildWidth(0)); 
  15.            childLeft = getRelativeChildOffset(0); 
  16.            //偏移量為0 
  17.            if (DEBUG) Log.d(TAG, "childLeft:"+childLeft);   
  18.  
  19.            // Calculate the variable page spacing if necessary 
  20.            // 如果mPageSpacing小于0的話,就重新計(jì)算mPageSpacing,并且給它賦值。 
  21.            if (mPageSpacing < 0) { 
  22.                setPageSpacing(((right - left) - getChildAt(0).getMeasuredWidth()) / 2); 
  23.            } 
  24.        } 
  25.  
  26.        for (int i = 0; i < childCount; i++) { 
  27.            final View child = getPageAt(i); 
  28.            if (child.getVisibility() != View.GONE) { 
  29.                final int childWidth = getScaledMeasuredWidth(child); 
  30.                final int childchildHeight = child.getMeasuredHeight(); 
  31.                int childTop = mPaddingTop
  32.                if (mCenterPagesVertically) { 
  33.                    childTop += ((getMeasuredHeight() - verticalPadding) - childHeight) / 2; 
  34.                } 
  35.                 
  36.                if (DEBUG) Log.d(TAG, "\tlayout-child" + i + ": " + childLeft + ", " + childTop); 
  37.                //把5個(gè)CellLayout布局到相應(yīng)的位置,layout的4個(gè)參數(shù)分別是 左、上、右、下。 
  38.                child.layout(childLeft, childTop, 
  39.                        childLeft + child.getMeasuredWidth(), childTop + childHeight); 
  40.                childLeft += childWidth + mPageSpacing; 
  41.            } 
  42.        } 
  43.        //***次布局完畢之后,就根據(jù)當(dāng)前頁(yè)偏移量(當(dāng)前頁(yè)距離Workspace最左邊的距離)滾動(dòng)到默認(rèn)的頁(yè)面去,***次布局時(shí) 
  44.        //默認(rèn)的當(dāng)前頁(yè)是3,則它的便宜量就是兩個(gè)CellLayout的寬度。 
  45.        if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) { 
  46.            setHorizontalScrollBarEnabled(false); 
  47.            int newX = getChildOffset(mCurrentPage) - getRelativeChildOffset(mCurrentPage); 
  48.            //滾動(dòng)到指定的位置 
  49.            scrollTo(newX, 0); 
  50.            mScroller.setFinalX(newX); 
  51.            if (DEBUG) Log.d(TAG, "newX is "+newX); 
  52.            setHorizontalScrollBarEnabled(true); 
  53.            mFirstLayout = false
  54.        } 
  55.  
  56.        if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) { 
  57.            mFirstLayout = false
  58.        } 
  59.    } 

 【51CTO.com獨(dú)家特稿,非經(jīng)授權(quán)謝絕轉(zhuǎn)載,合作媒體轉(zhuǎn)載請(qǐng)注明原文作者及出處!】

 

責(zé)任編輯:佚名 來(lái)源: 51CTO.com
相關(guān)推薦

2012-02-13 12:47:41

Android 4.0Launcher源碼分析

2012-01-11 16:02:56

Android 4.0Launcher源碼分析

2012-07-23 13:22:42

Intent Filt安全Android

2012-06-05 10:09:45

AndroidManiAndroidMani

2011-08-01 13:35:08

Android安全框架權(quán)限

2012-09-27 09:25:50

2012-07-16 10:21:48

Android進(jìn)程線程

2012-07-04 09:07:40

2011-08-12 09:06:48

Android系統(tǒng)應(yīng)用程序

2011-08-29 13:52:15

李洋Android應(yīng)用

2011-09-06 13:56:43

李洋iOS安全機(jī)制

2011-08-22 08:53:17

Android啟動(dòng)過(guò)程李洋

2010-05-28 17:30:58

SVN分支

2010-08-01 16:11:53

Android

2011-09-15 08:58:41

Android短信丟失技術(shù)原因

2021-11-08 15:06:15

鴻蒙HarmonyOS應(yīng)用

2012-02-15 10:05:02

Linux命令行

2010-11-08 16:58:36

OWASP專家采訪魏彩霞

2010-10-26 10:56:00

OWASP專家采訪夏鵬

2010-10-26 11:04:48

OWASP專家采訪方興
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)