學習資料

一、測試用例設計方法

白盒測試:邏輯覆蓋、循環(huán)覆蓋、基本路徑覆蓋

黑盒測試:邊界值分析法、等價類劃分、錯誤猜測法、因果圖法、狀態(tài)圖法、測試大綱法、隨機測試、場景法


二、軟件測試分為幾個階段 各階段的測試策略和要求(基礎)

試過程會依次經(jīng)歷:單元測試、集成測試、系統(tǒng)測試、驗收測試四個主要階段

單元測試:是針對軟件設計的最小單位(對于功能測試就是模塊)

集成測試:是將模塊按照設計要求組裝起來進行測試,主要目的是發(fā)現(xiàn)與接口有關的問題。

系統(tǒng)測試:是在集成測試通過后進行的,目的是充分運行系統(tǒng),驗證各子系統(tǒng)是否都能正常工作并完成設計的要求。

驗收測試:以需求階段的《需求規(guī)格說明書》為驗收標準,測試時模擬實際用戶的運行環(huán)境


三、你在測試中發(fā)現(xiàn)了一個bug,但是開發(fā)認為這不是一個bug,你應該怎樣解決(坑爹的溝通能力)

1、將問題提交到缺陷管理庫里面進行備案。

2、要獲取判斷的依據(jù)和標準:

3、根據(jù)需求說明書、產(chǎn)品說明、設計文檔等,確認實際結果是否與計劃有不一致的地方,提供缺陷是否確認的直接依據(jù);

4、如果沒有文檔依據(jù),可以根據(jù)類似軟件的一般特性來說明是否存在不一致的地方,來確認是否是缺陷;

5、與設計人員、開發(fā)人員和客戶代表等相關人員探討,確認是否是缺陷;


四、http與https區(qū)別(加密傳輸)

http協(xié)議和https協(xié)議的區(qū)別:傳輸信息安全性不同、連接方式不同、端口不同、證書zhuan申請方式不同、傳輸信息安全性不同

1、http協(xié)議:是超文本傳輸協(xié)議,信息是明文傳輸。如果攻擊者截取了Web瀏覽器和網(wǎng)站服務器之間的傳輸報文,就可以直接讀懂其中的信息;

2、https協(xié)議:是具有安全性的ssl加密傳輸協(xié)議,為瀏覽器和服務器之間的通信加密,確保數(shù)據(jù)傳輸?shù)陌踩?/p>

二、連接方式不同

1、http協(xié)議:http的連接很簡單,是無狀態(tài)的;

2、https協(xié)議:是由SSL+HTTP協(xié)議構建的可進行加密傳輸、身份認證的網(wǎng)絡協(xié)議。

三、端口不同

http協(xié)議:使用的端口是80;? ? ? ?https協(xié)議:使用的端口是443。

四、證書申請方式不同

http協(xié)議:免費申請? ? ? ? ? ? https協(xié)議:需要到ca申請證書,一般免費證書很少,需要交費

五、什么是負載測試

負載測試主要是考察軟件系統(tǒng)在既定負載下的性能表現(xiàn)。就是站在用戶的角度去觀察一定條件下軟件系統(tǒng)的性能表現(xiàn)。期望結果是用戶的性能指標需求得到滿足。性能指標一般體現(xiàn)為響應時間、并發(fā)量等。

六、python多線程

? ? ? ?python提供了兩個模塊來實現(xiàn)多線程thread?和threading?,thread?有一些缺點,在threading?得到了彌補,為了不浪費你和時間,所以我們直接學習threading?就可以了。




import?threading

首先導入threading?模塊,這是使用多線程的前提。


threads?=?[]

t1?=?threading.Thread(target=music,args=(u'愛情買賣',))

threads.append(t1)

  創(chuàng)建了threads數(shù)組,創(chuàng)建線程t1,使用threading.Thread()方法,在這個方法中調(diào)用music方法target=music,args方法對music進行傳參。?把創(chuàng)建好的線程t1裝到threads數(shù)組中。

  接著以同樣的方式創(chuàng)建線程t2,并把t2也裝到threads數(shù)組。


for?t?in?threads:

  t.setDaemon(True)

  t.start()

最后通過for循環(huán)遍歷數(shù)組。(數(shù)組被裝載了t1和t2兩個線程)

setDaemon()

  setDaemon(True)將線程聲明為守護線程,必須在start()?方法調(diào)用之前設置,如果不設置為守護線程程序會被無限掛起。子線程啟動后,父線程也繼續(xù)執(zhí)行下去,當父線程執(zhí)行完最后一條語句print?"all?over?%s"?%ctime()后,沒有等待子線程,直接就退出了,同時子線程也一同結束。

start()

開始線程活動。

? ??從執(zhí)行結果來看,子線程(muisc?、move?)和主線程(print?"all?over?%s"?%ctime())都是同一時間啟動,但由于主線程執(zhí)行完結束,所以導致子線程也終止。

們只對上面的程序加了個join()方法,用于等待線程終止。join()的作用是,在子線程完成運行之前,這個子線程的父線程將一直被阻塞。

注意: ?join()方法的位置是在for循環(huán)外的,也就是說必須等待for循環(huán)里的兩個進程都結束后,才去執(zhí)行主進程。

從執(zhí)行結果可看到,music?和move?是同時啟動的。

  開始時間4分11秒,直到調(diào)用主進程為4分22秒,總耗時為10秒。從單線程時減少了2秒,我們可以把music的sleep()的時間調(diào)整為4秒。

七、數(shù)據(jù)庫中where與having的區(qū)別

????從整體聲明角度分析:

  “where”是一個約束聲明,在查詢數(shù)據(jù)庫結果返回之前對數(shù)據(jù)庫的查詢條件做一個約束,即返回結果之前起作用,“where”后面不能跟聚合函數(shù);

  “having”是一個過濾聲明,在查詢數(shù)據(jù)庫結果返回之后進行過濾,即返回結果之后起作用,“having”后面可以加聚合函數(shù);

聚合函數(shù):是對一組值進行計算,返回單一的值,例如:count(),sum(),max(),min()

從使用角度分析:

  “where”?? select? student_id,student_name from student where student_sorce>80;

  "having"? select sum(sorce) from student group by student_sex having student_id<10;


八、java中String、StringBuffer和StringBuilder的區(qū)別

java中用于處理字符串常用的有三個類:

1、java.lang.String

2、java.lang.StringBuffer

3、java.lang.StrungBuilder

三者共同之處:都是final類,不允許被繼承,主要是從性能和安全性上考慮的,因為這幾個類都是經(jīng)常被使用著,且考慮到防止其中的參數(shù)被參數(shù)修改影響到其他的應用。

StringBuffer是線程安全,可以不需要額外的同步用于多線程中;

StringBuilder是非同步,運行于多線程中就需要使用著單獨同步處理,但是速度就比StringBuffer快多了;

StringBuffer與StringBuilder兩者共同之處:可以通過append、indert進行字符串的操作。

String實現(xiàn)了三個接口:Serializable、Comparable<String>、CarSequence

StringBuilder只實現(xiàn)了兩個接口Serializable、CharSequence,相比之下String的實例可以通過compareTo方法進行比較,其他兩個不可以。

這三個類之間的區(qū)別主要是在兩個方面,即運行速度和線程安全這兩方面。

1、首先說運行速度,或者說是執(zhí)行速度,在這方面運行速度快慢為:StringBuilder > StringBuffer > String

  String最慢的原因:String為字符串常量,而StringBuilder和StringBuffer均為字符串變量,即String對象一旦創(chuàng)建之后該對象是不可更改的,但后兩者的對象是變量,是可以更改的。以下面一段代碼為例:

運行這段代碼會發(fā)現(xiàn)先輸出“abc”,然后又輸出“abcde”,好像是str這個對象被更改了,其實,這只是一種假象罷了,JVM對于這幾行代碼是這樣處理的,首先創(chuàng)建一個String對象str,并把“abc”賦值給str,然后在第三行中,其實JVM又創(chuàng)建了一個新的對象也名為str,然后再把原來的str的值和“de”加起來再賦值給新的str,而原來的str就會被JVM的垃圾回收機制(GC)給回收掉了,所以,str實際上并沒有被更改,也就是前面說的String對象一旦創(chuàng)建之后就不可更改了。所以,Java中對String對象進行的操作實際上是一個不斷創(chuàng)建新的對象并且將舊的對象回收的一個過程,所以執(zhí)行速度很慢。而StringBuilder和StringBuffer的對象是變量,對變量進行操作就是直接對該對象進行更改,而不進行創(chuàng)建和回收的操作,所以速度要比String快很多。另外,有時候我們會這樣對字符串進行賦值

1 String str="abc"+"de";

2 StringBuilder stringBuilder=newStringBuilder().append("abc").append("de");

3 System.out.println(str);

4 System.out.println(stringBuilder.toString());


這樣輸出結果也是“abcde”和“abcde”,但是String的速度卻比StringBuilder的反應速度要快很多,這是因為第1行中的操作和String str="abcde";是完全一樣的,所以會很快,而如果寫成下面這種形式

1 String str1="abc";

2 String str2="de";

3 String str=str1+str2;

那么JVM就會像上面說的那樣,不斷的創(chuàng)建、回收對象來進行這個操作了。速度就會很慢。


public static void main(String[] args) {

? ? ? ? long a=new Date().getTime();

? ? ? ? String cc="";

? ? ? ? int n=10000;

? ? ? ? for (int i = 0; i < n; i++) {

? ? ? ? ? ? cc+="."+i;

? ? ? ? }

? ? ? ? System.out.println("String使用的時間"+(System.currentTimeMillis()-a)/1000.0+"s");

? ? ? ? long s1=System.currentTimeMillis();

? ? ? ? StringBuilder sb=new StringBuilder();

? ? ? ? for (int i = 0; i < n; i++) {

? ? ? ? ? ? sb.append("."+i);

? ? ? ? }

? ? ? ? System.out.println("StringBuilder使用的時間"+(System.currentTimeMillis()-s1)/1000.0+"s");

? ? ? ? long s2=System.currentTimeMillis();

? ? ? ? StringBuffer sbf=new StringBuffer();

? ? ? ? for (int i = 0; i < n; i++) {

? ? ? ? ? ? sbf.append("."+i);

? ? ? ? }

? ? ? ? System.out.println("StringBuffer使用的時間"+(System.currentTimeMillis()-s2)/1000.0+"s");

? ? }


2. 再來說線程安全

在線程安全上,StringBuilder是線程不安全的,而StringBuffer是線程安全的

  如果一個StringBuffer對象在字符串緩沖區(qū)被多個線程使用時,StringBuffer中很多方法可以帶有synchronized關鍵字,所以可以保證線程是安全的,但StringBuilder的方法則沒有該關鍵字,所以不能保證線程安全,有可能會出現(xiàn)一些錯誤的操作。所以如果要進行的操作是多線程的,那么就要使用StringBuffer,但是在單線程的情況下,還是建議使用速度比較快的StringBuilder。

(一個線程訪問一個對象中的synchronized(this)同步代碼塊時,其他試圖訪問該對象的線程將被阻塞)

3. 總結一下 

   String:適用于少量的字符串操作的情況

   StringBuilder:適用于單線程下在字符緩沖區(qū)進行大量操作的情況

   StringBuffer:適用多線程下在字符緩沖區(qū)進行大量操作的情況

九、java的三大特性和他們之間的區(qū)別

十、hashmap和map的關系

十一、數(shù)組和鏈表的區(qū)別

十二、垃圾回收機制算法和原理

十三、tcp,udp的區(qū)別

十四、jmeter性能測試

十五、seleuinm原理和缺點

十六、什么是非對稱加密和對稱加密

十七、python裝飾器起什么作用,原理是什么

十八、linux常用的指令

十九、手寫一個排序算法

二十、重載和重寫的區(qū)別

二十一、GC機制、Java引用類型

二十二、RecyclerView和ListView的區(qū)別

一、 緩存機制對比

1. 層級不同:

RecyclerView比ListView多兩級緩存,支持多個離ItemView緩存,支持開發(fā)者自定義緩存處理邏輯,支持所有RecyclerView共用同一個RecyclerViewPool(緩存池)。

具體來說:

ListView(兩級緩存):

RecyclerView(四級緩存):

ListView和RecyclerView緩存機制基本一致:

1). mActiveViews和mAttachedScrap功能相似,意義在于快速重用屏幕上可見的列表項ItemView,而不需要重新createView和bindView;

2). mScrapView和mCachedViews + mReyclerViewPool功能相似,意義在于緩存離開屏幕的ItemView,目的是讓即將進入屏幕的ItemView重用.

3). RecyclerView的優(yōu)勢在于a.mCacheViews的使用,可以做到屏幕外的列表項ItemView進入屏幕內(nèi)時也無須bindView快速重用;b.mRecyclerPool可以供多個RecyclerView共同使用,在特定場景下,如viewpaper+多個列表頁下有優(yōu)勢.客觀來說,RecyclerView在特定場景下對ListView的緩存機制做了補強和完善。

2. 緩存不同:

1). RecyclerView緩存RecyclerView.ViewHolder,抽象可理解為:

View + ViewHolder(避免每次createView時調(diào)用findViewById) + flag(標識狀態(tài));

RecyclerView中mCacheViews(屏幕外)獲取緩存時,是通過匹配pos獲取目標位置的緩存,這樣做的好處是,當數(shù)據(jù)源數(shù)據(jù)不變的情況下,無須重新bindView:

2). ListView緩存View。而同樣是離屏緩存,ListView從mScrapViews根據(jù)pos獲取相應的緩存,但是并沒有直接使用,而是重新getView(即必定會重新bindView)。

二、 局部刷新

RecyclerView更大的亮點在于提供了局部刷新的接口,通過局部刷新,就能避免調(diào)用許多無用的bindView。ListView和RecyclerView最大的區(qū)別在于數(shù)據(jù)源改變時的緩存的處理邏輯,ListView是"一鍋端",將所有的mActiveViews都移入了二級緩存mScrapViews,而RecyclerView則是更加靈活地對每個View修改標志位,區(qū)分是否重新bindView。

ListView獲取緩存的流程:

RecyclerView獲取緩存的流程:

結合RecyclerView的緩存機制,看看局部刷新是如何實現(xiàn)的:

以RecyclerView中notifyItemRemoved(1)為例,最終會調(diào)用requestLayout(),使整個RecyclerView重新繪制,過程為:

onMeasure()–>onLayout()–>onDraw()

其中,onLayout()為重點,分為三步:

dispathLayoutStep1():記錄RecyclerView刷新前列表項ItemView的各種信息,如Top,Left,Bottom,Right,用于動畫的相關計算;

dispathLayoutStep2():真正測量布局大小,位置,核心函數(shù)為layoutChildren();

dispathLayoutStep3():計算布局前后各個ItemView的狀態(tài),如Remove,Add,Move,Update等,如有必要執(zhí)行相應的動畫.

其中,layoutChildren()流程圖:

當調(diào)用notifyItemRemoved時,會對屏幕內(nèi)ItemView做預處理,修改ItemView相應的pos以及flag(流程圖中紅色部分):

當調(diào)用fill()中RecyclerView.getViewForPosition(pos)時,RecyclerView通過對pos和flag的預處理,使得bindview只調(diào)用一次.

作者:衛(wèi)宮士郎

鏈接:http://m.itdecent.cn/p/257c279a3493

來源:簡書

著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。

二十三、Android/ 布局優(yōu)化

二十四、Activity的四種啟動模式

Activity四種啟動模式分別是standard,singleTop,singleTask,singltInstance.在執(zhí)行各個模式時候的頁面中執(zhí)行的方法各不相同,我們常常只是口頭敘述一下各種模式是怎么回事,但是真的被問到執(zhí)行的方法,可能說的不是很清楚,這里通過打印log的方法記錄一下。

standard模式


從MainActivity進入StandardActivity,執(zhí)行的方法分別是:onCreate,onStart,onResume,onAttchedToWindow.

從StandardActivity進入StandardTestActivity后執(zhí)行方法:onPause,onStop.可以看到,當StandardTestActivity執(zhí)行完onResume后,StandardActivity的onStop方法才執(zhí)行。


返回的時候可以看到從StandardTestActivity到StandardActivity,StandardActivity執(zhí)行了onStart,onResume方法,而當StandardActivity的onResume方法執(zhí)行后,StandardTestActivity執(zhí)行了onStop,onDestroy,onDetachedFromWindow方法


再次點擊返回從StandardActivity返回到MainActivity頁面,StandardActivity也依次執(zhí)行了onPause,onStop,onDestroy,onDetachedFromWindow方法

singleTop模式


如圖所示,這里分兩種情況來看SingleTopActivity方法的執(zhí)行。

singleTop—>singleTop

singleTop—>standard—>singleTop

singleTop–>singleTop

可以從圖中看到singleTop->singleTop不再執(zhí)行依次onCreate,onStart,onResume,而是執(zhí)行了onNewIntent,onResume.


singleTop–>standard–>singleTop

可以從圖中看到singleTop-->standard-->singleTop中,第二個singleTop依次執(zhí)行了onCreate,onStart,onResume方法


singleTask模式


如圖所示,同樣分兩種情況來看SingleTaskActivity方法的執(zhí)行。

singleTask—>singleTask

singleTask—>standard—>singleTask

singleTask–>singleTask

可以從圖中看到,singleTask->singleTask和singleTop->singleTop類似,也是執(zhí)行了onNewIntent,onResume方法


singleTask–>standard–>singleTask

可以從圖中看到singleTask-->standard-->singleTask ,進入第二個singleTask的時候,StandardActivity執(zhí)行的方法相當于finish的操作,也就是被移除了,singleTask則執(zhí)行了onNewIntent,onStart,onResume方法。

返回的時候直接執(zhí)行了singleTask的onPause,onStop,onDestroy,onDetachedFromWindow方法



singleInstance模式


如圖所示,同樣分兩種情況來看SingleInstanceActivity方法的執(zhí)行。

singleInstance–>singleInstance

singleInstance–>standard–>singleInstance

singleInstance–>singleInstance

可以從圖中看到,singleInstance->singleInstance同樣是執(zhí)行了onNewIntent,onResume,前一個執(zhí)行了onPause方法


singleInstance–>standard–>singleInstance

可以從圖中看到,前面的一切正常,進入第二個SingleInstanceActivity的時候,執(zhí)行了onNewIntent,onStart,onResume方法,這個和singleTask是一樣的,但是不同的是SingleInstanceActivity和StandardActivity不在同一個任務棧中。


從下圖可以看到,SingleInstanceActivity點擊返回到了StandardActivity中,再點擊返回,則不再會回到SingleInstanceActivity。


二十五、Handler機制,loop方法為何不會造成ANR

二十六、Android之View的繪制流程解析

一:繪制大致流程

一個APP由許多Activity組成,每個Activity都對應一個界面呈現(xiàn)給用戶,而每一個界面都是由各種View和ViewGroup組成,總體結構是一個樹形結構,如圖所示:


在上圖中,DecorView是所有視圖的根視圖,也就是最頂層布局,它是一個ViewGroup。每個Activity的View繪制流程都是先從DecorView的繪制開始,然后依次遞歸繪制它的子View和子ViewGroup,子ViewGroup再遞歸繪制它包含的子View,直到所有的View都繪制完成。

二:View繪制涉及到的類和方法

View繪制的入口是ViewRootImpl類的performTraversals()方法。在performTraversals()方法中有3個重要的步驟方法:

(1)performMeasure():該方法主要用于測量所有View和ViewGroup的大?。▽捄透撸?/p>

(2)performLayout():該方法用于確定所有View和ViewGroup在父布局的位置

(3)performDraw():該方法進行具體的繪制操作

三:performMeasure測量

1.測量涉及的方法

performMeasure()主要就是用來測量View和ViewGroup的寬和高,涉及到的方法有:

(1)View:Measure()—>onMeasure()—>setMeasureDimension()—>getDefaultSize()。

View的測量流程:View的測量是從Measure()方法開始的,在Measure()里面沒有具體的操作,而是直接調(diào)用onMeasure()方法。在onMeasure()方法里調(diào)用了兩個getDefaultSize()方法來分別測量View的寬和高的值。最后調(diào)用setMeasureDimension()方法將View的寬和高測量值保存下來。

(2)ViewGroup:Measure()—>onMeasure()—>measureChildren()—>measureChild()/measureChildWithMargins()—>Measure()—>onMeasure()—>setMeasureDimension()—>getDefaultSize()。

ViewGroup除了需要測量自己的寬高大小,還需要測量它包含的子View或子ViewGroup的大小,所以它涉及到的方法除了測量View需要的方法之外,還有measureChildren()方法,在measureChildren()方法內(nèi)通過循環(huán)調(diào)用measureChild()方法,在measureChild方法中又調(diào)用子View或子ViewGroup的Measure()方法。

總結:在performMeasure()方法中首先調(diào)用的是頂級視圖DecorView的Measure()方法,在Measure()方法中調(diào)用onMeasure()方法進行DecorView的寬高大小測量。由于DecorView是一個ViewGroup,所以在onMeasure()方法內(nèi)又調(diào)用了measureChildren()方法來測量它的子View和子ViewGroup寬高大小,這樣一步步往下遞歸遍歷,最后測量出所有的View和ViewGroup的大小。

2.MeasureSpec

? ? ? ? 上面描述了測量View和ViewGroup大小的大致流程,但是在具體測量的時候還涉及到了一個MeasureSpec類,這個類是View類的內(nèi)部類,主要內(nèi)容是一個int型變量,int是32位的,其中高2位表示模式(Mode),低30位表示大?。⊿ize)。每一個View和ViewGroup都有自己的MeasureSpec,具體來說是有2個MeasureSpec:widthMeasureSpec和heightMeasureSpec。這兩個MeasureSpec從measure()方法開始作為參數(shù),一直傳遞到getDefaultSize()方法,最后在getDefaultSize()方法里面參考這2個MeasureSpec來確定具體大小。

MeasureSpec高2位表示的模式有3種:UNSPECIFIED(不指定的)、EXACTLY(確定的)、AT_MOST(至多的)。

MeasureSpec到底有什么用?

子View的大小通常是受限于父布局的,舉個例子,假如某個子View大小設為match_parent,那么該子View的大小就依賴于父布局的大小,父布局如果大小為200*200dp,子View就為200*200dp。

子View的MeasureSpec是由自身的LayoutParams和父布局的MeasureSpec共同確定的。在上面例子中父布局大小為200*200dp,于是父布局的widthMeasureSpec和widthMeasureSpec模式Mode為EXACTLY(確定的),大小Size為200。又由于子View的LayoutParams指定為match_parent,于是子View的widthMeasureSpec和widthMeasureSpec模式Mode也為EXACTLY(確定的),大小Size也為200。

上面子View的MeasureSpec確定過程發(fā)生在measureChild()方法中,確定好子View的MeasureSpec后就將其作為參數(shù)傳入到measure()方法,最后在getDefaultSize()方法里根據(jù)子View的兩個MeasureSpec來確定子View的寬高。

父MeasureSpec和子MeasureSpec的關系圖如下,上面例子對應下圖的第二行第一列。


上圖總結:

1.當子View的LayoutParams指定為具體的尺寸如200*200dp,那么無論父布局的MeasureSpec模式和大小是什么,子View的模式都為EXACTLY(確定的),大小就是LayoutParams指定的具體值200,而不依賴于父布局MeasureSpec指定的大小。

2.當子View的LayoutParams指定為match_parent時,子View的MeasureSpec就和父布局的MeasureSpec相同。

2.當子View的LayoutParams指定為wrap_content時,分兩種情況:當父布局MeasureSpec模式為UNSPECIFIED(不指定的),子View的MeasureSpec模式也是UNSPECIFIED(不指定的);當父布局MeasureSpec模式為EXACTLY(確定的)和AT_MOST(至多的),子View的MeasureSpec模式都是AT_MOST(至多的)。無論Mode是哪一種,子View的MeasureSpec的大?。⊿ize)都是父布局的MeasureSpec中指定的大小,表示子View大小不應該超過父布局大小。

只要知道了父布局的MeasureSpec和子View的LayoutParams,那么子View的MeasureSpec也就確定了,從而能夠進一步確定子View的大小。

ps:由于DecorView是頂級布局,所以它的MeasureSpec是通過窗口大小和自身的LayoutParams確定的。

四:performLayout布局

在performTraversals()方法中,首先調(diào)用performMeasure()方法來測量所有View和ViewGroup的寬高大小。之后就是調(diào)用performLayout()方法確定每個View和ViewGroup在其父布局中的位置。

布局涉及的方法

(1)View:layout()—>setFrame()

View布局流程:View通過調(diào)用layout()方法來確定它在父布局的位置,具體是在layout()方法內(nèi)調(diào)用setFrame()方法,將該View的上下左右四個點位置作為參數(shù)傳入,從而確定了View在父布局的位置。

ViewGroup:layout()—>setFrame()—>onLayout()

ViewGroup布局流程:ViewGroup同樣先調(diào)用layout()方法,通過layout()方法內(nèi)的setFrame()方法設置自己相對于父布局的位置。但是由于ViewGroup包含子View或子ViewGroup,所以需要重寫onLayout()方法,在onLayout()方法中遍歷自己的子View或子ViewGroup,分別調(diào)用它們的layout()方法來完成子View或子ViewGroup的布局。

總結:在performLayout()方法中首先調(diào)用的是頂級布局DecorView的Layout()方法,由于DecorView是一個ViewGroup,所以它調(diào)用的是父類View的layout()方法(原因在下面PS中介紹),并且在layout()方法中確定了自己的位置之后再重寫onLayout()方法來遍歷子View和子ViewGroup,通過調(diào)用View和ViewGroup的layout()方法來確定它們在父布局DecorView中的位置,這樣一步步往下遞歸遍歷,直到所有的View都確定了在父布局的位置為止。

PS:

1.ViewGroup的layout()方法是final修飾的,不能被重寫;View的layout()方法是可以被重寫的。

2.在ViewGroup中l(wèi)ayout()方法中最終調(diào)用的是View的layout()方法。

2.View的onLayout()方法是一個空方法,這是因為View沒有子View或子ViewGroup,不需要onLayout()方法。而ViewGroup的onLayout()方法是一個抽象方法,即ViewGroup的子類必須重寫這個方法,因為ViewGroup包含子View或子ViewGroup,需要在onLayout()方法中遍歷View或子ViewGroup并調(diào)用它們的layout()方法,從而確定它們在父布局中的位置。

五:performDraw繪制

在performTraversals()方法中,首先調(diào)用performMeasure()方法來測量所有View和ViewGroup的寬高大小。之后就是調(diào)用performLayout()方法確定每個View和ViewGroup在其父布局中的位置。最后就是調(diào)用performDraw進行具體的繪制。

繪制涉及的方法:

View:draw()—>drawBackground()—>onDraw()—>onDrawScrollBars()。

View繪制流程:首先調(diào)用的是draw()方法,在該方法內(nèi)依次調(diào)用drawBackground()方法來繪制View背景,調(diào)用onDraw()方法繪制View內(nèi)容,最后調(diào)用onDrawScrollBars()方法繪制裝飾。

ViewGroup:draw()—>drawBackground()—>onDraw()—>dispatchDraw()—>onDrawScrollBars()。

ViewGroup繪制流程:在ViewGroup的draw()方法中,在調(diào)用drawBackground()方法來繪制View背景、調(diào)用onDraw()方法繪制View內(nèi)容之后還需要調(diào)用dispatchDraw()方法來繪制子View和子ViewGroup,具體是在dispatchDraw()方法內(nèi)循環(huán)遍歷子View和子ViewGroup,并且調(diào)用它們的draw()方法進行繪制。

總結:在performDraw()方法中首先調(diào)用頂級布局DecorView的draw()方法繪制自身,由于DecorView是一個ViewGroup,所以在繪制完自己之后還要調(diào)用dispatchDraw()方法來遍歷繪制它的子View和子ViewGroup。這樣一步步往下遞歸遍歷繪制,直到所有View和ViewGroup都繪制完成為止。

PS:在View類中的onDraw()方法為空方法,具體的繪制邏輯需要在子類中的onDraw()方法中實現(xiàn)。


二十七、equals和==區(qū)別

二十八、Array和Linked區(qū)別

二十九、線程池

三十、進程間通信方式

三十一、Android中PX、DP、SP的區(qū)別

px : 其實就是像素單位,比如我們通常說的手機分辨列表800*400都是px的單位

sp : 同dp相似,還會根據(jù)用戶的字體大小偏好來縮放

dp : 虛擬像素,在不同的像素密度的設備上會自動適配

dip: 同dp

三十二、Android之View的繪制流程解析

https://blog.csdn.net/yuncaidaishu/article/details/100018089

三十三、Android持久化存儲的幾種方式

https://blog.csdn.net/qq_35700731/article/details/78781540

三十四、JMeter性能測試

https://blog.csdn.net/u012111923/article/details/80705141

三十五、

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容