學(xué)習(xí)資料

一、測(cè)試用例設(shè)計(jì)方法

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

黑盒測(cè)試:邊界值分析法、等價(jià)類(lèi)劃分、錯(cuò)誤猜測(cè)法、因果圖法、狀態(tài)圖法、測(cè)試大綱法、隨機(jī)測(cè)試、場(chǎng)景法


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

試過(guò)程會(huì)依次經(jīng)歷:?jiǎn)卧獪y(cè)試、集成測(cè)試、系統(tǒng)測(cè)試、驗(yàn)收測(cè)試四個(gè)主要階段

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

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

系統(tǒng)測(cè)試:是在集成測(cè)試通過(guò)后進(jìn)行的,目的是充分運(yùn)行系統(tǒng),驗(yàn)證各子系統(tǒng)是否都能正常工作并完成設(shè)計(jì)的要求。

驗(yàn)收測(cè)試:以需求階段的《需求規(guī)格說(shuō)明書(shū)》為驗(yàn)收標(biāo)準(zhǔn),測(cè)試時(shí)模擬實(shí)際用戶(hù)的運(yùn)行環(huán)境


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

1、將問(wèn)題提交到缺陷管理庫(kù)里面進(jìn)行備案。

2、要獲取判斷的依據(jù)和標(biāo)準(zhǔn):

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

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

5、與設(shè)計(jì)人員、開(kāi)發(fā)人員和客戶(hù)代表等相關(guān)人員探討,確認(rèn)是否是缺陷;


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

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

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

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

二、連接方式不同

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

2、https協(xié)議:是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議。

三、端口不同

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

四、證書(shū)申請(qǐng)方式不同

http協(xié)議:免費(fèi)申請(qǐng)? ? ? ? ? ? https協(xié)議:需要到ca申請(qǐng)證書(shū),一般免費(fèi)證書(shū)很少,需要交費(fèi)

五、什么是負(fù)載測(cè)試

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

六、python多線程

? ? ? ?python提供了兩個(gè)模塊來(lái)實(shí)現(xiàn)多線程thread?和threading?,thread?有一些缺點(diǎn),在threading?得到了彌補(bǔ),為了不浪費(fèi)你和時(shí)間,所以我們直接學(xué)習(xí)threading?就可以了。




import?threading

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


threads?=?[]

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

threads.append(t1)

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

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


for?t?in?threads:

  t.setDaemon(True)

  t.start()

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

setDaemon()

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

start()

開(kāi)始線程活動(dòng)。

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

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

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

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

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

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

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

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

  “having”是一個(gè)過(guò)濾聲明,在查詢(xún)數(shù)據(jù)庫(kù)結(jié)果返回之后進(jìn)行過(guò)濾,即返回結(jié)果之后起作用,“having”后面可以加聚合函數(shù);

聚合函數(shù):是對(duì)一組值進(jìn)行計(jì)算,返回單一的值,例如: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中用于處理字符串常用的有三個(gè)類(lèi):

1、java.lang.String

2、java.lang.StringBuffer

3、java.lang.StrungBuilder

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

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

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

StringBuffer與StringBuilder兩者共同之處:可以通過(guò)append、indert進(jìn)行字符串的操作。

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

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

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

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

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

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

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

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

3 System.out.println(str);

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


這樣輸出結(jié)果也是“abcde”和“abcde”,但是String的速度卻比StringBuilder的反應(yīng)速度要快很多,這是因?yàn)榈?行中的操作和String str="abcde";是完全一樣的,所以會(huì)很快,而如果寫(xiě)成下面這種形式

1 String str1="abc";

2 String str2="de";

3 String str=str1+str2;

那么JVM就會(huì)像上面說(shuō)的那樣,不斷的創(chuàng)建、回收對(duì)象來(lái)進(jìn)行這個(gè)操作了。速度就會(huì)很慢。


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使用的時(shí)間"+(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使用的時(shí)間"+(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使用的時(shí)間"+(System.currentTimeMillis()-s2)/1000.0+"s");

? ? }


2. 再來(lái)說(shuō)線程安全

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

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

(一個(gè)線程訪問(wèn)一個(gè)對(duì)象中的synchronized(this)同步代碼塊時(shí),其他試圖訪問(wèn)該對(duì)象的線程將被阻塞)

3. 總結(jié)一下 

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

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

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

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

十、hashmap和map的關(guān)系

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

十二、垃圾回收機(jī)制算法和原理

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

十四、jmeter性能測(cè)試

十五、seleuinm原理和缺點(diǎn)

十六、什么是非對(duì)稱(chēng)加密和對(duì)稱(chēng)加密

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

十八、linux常用的指令

十九、手寫(xiě)一個(gè)排序算法

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

二十一、GC機(jī)制、Java引用類(lèi)型

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

一、 緩存機(jī)制對(duì)比

1. 層級(jí)不同:

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

具體來(lái)說(shuō):

ListView(兩級(jí)緩存):

RecyclerView(四級(jí)緩存):

ListView和RecyclerView緩存機(jī)制基本一致:

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

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

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

2. 緩存不同:

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

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

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

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

二、 局部刷新

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

ListView獲取緩存的流程:

RecyclerView獲取緩存的流程:

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

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

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

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

dispathLayoutStep1():記錄RecyclerView刷新前列表項(xiàng)ItemView的各種信息,如Top,Left,Bottom,Right,用于動(dòng)畫(huà)的相關(guān)計(jì)算;

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

dispathLayoutStep3():計(jì)算布局前后各個(gè)ItemView的狀態(tài),如Remove,Add,Move,Update等,如有必要執(zhí)行相應(yīng)的動(dòng)畫(huà).

其中,layoutChildren()流程圖:

當(dāng)調(diào)用notifyItemRemoved時(shí),會(huì)對(duì)屏幕內(nèi)ItemView做預(yù)處理,修改ItemView相應(yīng)的pos以及flag(流程圖中紅色部分):

當(dāng)調(diào)用fill()中RecyclerView.getViewForPosition(pos)時(shí),RecyclerView通過(guò)對(duì)pos和flag的預(yù)處理,使得bindview只調(diào)用一次.

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

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

來(lái)源:簡(jiǎn)書(shū)

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

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

二十四、Activity的四種啟動(dòng)模式

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

standard模式


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

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


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


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

singleTop模式


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

singleTop—>singleTop

singleTop—>standard—>singleTop

singleTop–>singleTop

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


singleTop–>standard–>singleTop

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


singleTask模式


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

singleTask—>singleTask

singleTask—>standard—>singleTask

singleTask–>singleTask

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


singleTask–>standard–>singleTask

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

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



singleInstance模式


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

singleInstance–>singleInstance

singleInstance–>standard–>singleInstance

singleInstance–>singleInstance

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


singleInstance–>standard–>singleInstance

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


從下圖可以看到,SingleInstanceActivity點(diǎn)擊返回到了StandardActivity中,再點(diǎn)擊返回,則不再會(huì)回到SingleInstanceActivity。


二十五、Handler機(jī)制,loop方法為何不會(huì)造成ANR

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

一:繪制大致流程

一個(gè)APP由許多Activity組成,每個(gè)Activity都對(duì)應(yīng)一個(gè)界面呈現(xiàn)給用戶(hù),而每一個(gè)界面都是由各種View和ViewGroup組成,總體結(jié)構(gòu)是一個(gè)樹(shù)形結(jié)構(gòu),如圖所示:


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

二:View繪制涉及到的類(lèi)和方法

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

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

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

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

三:performMeasure測(cè)量

1.測(cè)量涉及的方法

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

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

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

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

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

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

2.MeasureSpec

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

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

MeasureSpec到底有什么用?

子View的大小通常是受限于父布局的,舉個(gè)例子,假如某個(gè)子View大小設(shè)為match_parent,那么該子View的大小就依賴(lài)于父布局的大小,父布局如果大小為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確定過(guò)程發(fā)生在measureChild()方法中,確定好子View的MeasureSpec后就將其作為參數(shù)傳入到measure()方法,最后在getDefaultSize()方法里根據(jù)子View的兩個(gè)MeasureSpec來(lái)確定子View的寬高。

父MeasureSpec和子MeasureSpec的關(guān)系圖如下,上面例子對(duì)應(yīng)下圖的第二行第一列。


上圖總結(jié):

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

2.當(dāng)子View的LayoutParams指定為match_parent時(shí),子View的MeasureSpec就和父布局的MeasureSpec相同。

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

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

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

四:performLayout布局

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

布局涉及的方法

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

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

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

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

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

PS:

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

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

2.View的onLayout()方法是一個(gè)空方法,這是因?yàn)閂iew沒(méi)有子View或子ViewGroup,不需要onLayout()方法。而ViewGroup的onLayout()方法是一個(gè)抽象方法,即ViewGroup的子類(lèi)必須重寫(xiě)這個(gè)方法,因?yàn)閂iewGroup包含子View或子ViewGroup,需要在onLayout()方法中遍歷View或子ViewGroup并調(diào)用它們的layout()方法,從而確定它們?cè)诟覆季种械奈恢谩?/p>

五:performDraw繪制

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

繪制涉及的方法:

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

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

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

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

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

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


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

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

二十九、線程池

三十、進(jìn)程間通信方式

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

px : 其實(shí)就是像素單位,比如我們通常說(shuō)的手機(jī)分辨列表800*400都是px的單位

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

dp : 虛擬像素,在不同的像素密度的設(shè)備上會(huì)自動(dòng)適配

dip: 同dp

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

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

三十三、Android持久化存儲(chǔ)的幾種方式

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

三十四、JMeter性能測(cè)試

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

三十五、

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

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

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