目錄
Toast可以在子線程使用
估值器和插值器
Activity啟動(dòng)過程
Intent能傳遞的數(shù)據(jù)類型
Parcelable和Serializable區(qū)別
Instrumentation
WMS和AMS的窗口切換過程
ListView局部刷新
Android中App的內(nèi)存大小胎撇、largeHeap的大小
在onCreate中用子線程給TextView屬性賦值成功的問題
性能分析工具
線性布局的幾個(gè)問題
Toast可以在子線程使用
Toast是系統(tǒng)Window巨双,不受ViewTree刷新時(shí)checkThread的限制悟耘。
但是Toast不能隨便在子線程使用鲤看,需要子線程啟動(dòng)Looper,或者是handlerthread几缭。
因?yàn)閠oast需要讓notification manager service 回調(diào)自己派桩,這是通過bindler回調(diào)的腾誉,回調(diào)會(huì)進(jìn)入Bindler線程椭盏,不是直接回到發(fā)起toast的線程组砚,這就需要該線程有l(wèi)ooper,這樣才能用handler通知到調(diào)用Toast的線程掏颊。
估值器和插值器
估值器和插值器是用于屬性動(dòng)畫ObjectAnimator的糟红,原理是不斷調(diào)用get和set方法來重設(shè)屬性值,比補(bǔ)間動(dòng)畫的形式更加豐富。
屬性動(dòng)畫中的估值器和插值器盆偿,是實(shí)現(xiàn)非勻速動(dòng)畫的掩蛤,根據(jù)當(dāng)前屬性改變的百分比,計(jì)算改變后的屬性值陈肛。
插值器Interpolator決定變化的趨勢(shì),可以根據(jù)時(shí)間流逝的百分比兄裂,計(jì)算屬性改變的百分比句旱。
估值器Evaluator設(shè)置變化的具體數(shù)值,讓屬性值從初始值過渡到結(jié)束值晰奖。
過程插值器根據(jù)input的時(shí)間谈撒,計(jì)算出屬性變化的百分比fraction,插值器根據(jù)百分百fraction匾南,結(jié)合動(dòng)畫的初始值startValue和結(jié)束值endValue啃匿,計(jì)算出當(dāng)下的屬性值
大致流程如下:
屬性動(dòng)畫中的插值器和估值器
Activity啟動(dòng)過程
1.Activity中最終到startActivityForResult()(mMainThread.getApplicationThread()傳入了一個(gè)ApplicationThread檢查APT)
->Instrumentation#execStartActivity()和checkStartActivityResult()(這是在啟動(dòng)了Activity之后判斷Activity是否啟動(dòng)成功,例如沒有在AM中注冊(cè)那么就會(huì)報(bào)錯(cuò))
->ActivityManagerNative.getDefault().startActivity()(類似AIDL蛆楞,實(shí)現(xiàn)了IAM溯乒,實(shí)際是由遠(yuǎn)端的AMS實(shí)現(xiàn)startActivity())
->ActivityStackSupervisor#startActivityMayWait()
->ActivityStack#resumeTopActivityInnerLocked
->ActivityStackSupervisor#realStartActivityLocked()(在這里調(diào)用APT的scheduleLaunchActivity,也是AIDL,不過是在遠(yuǎn)端調(diào)起了本進(jìn)程Application線程)
->ApplicationThread#scheduleLaunchActivity()(這是本進(jìn)程的一個(gè)線程豹爹,用于作為Service端來接受AMS client端的調(diào)起)
->ActivityThread#handleLaunchActivity()(接收內(nèi)部類H的消息裆悄,ApplicationThread線程發(fā)送LAUNCH_ACTIVITY消息給H)
->最終在ActivityThread#performLaunchActivity()中實(shí)現(xiàn)Activity的啟動(dòng)完成了以下幾件事:
2.從傳入的ActivityClientRecord中獲取待啟動(dòng)的Activity的組件信息
3.創(chuàng)建類加載器,使用Instrumentation#newActivity()加載Activity對(duì)象
4.調(diào)用LoadedApk.makeApplication方法嘗試創(chuàng)建Application臂聋,由于LoadedApk只有package一個(gè)單例所以不會(huì)重復(fù)創(chuàng)建光稼。
5.創(chuàng)建Context的實(shí)現(xiàn)類ContextImpl對(duì)象,并通過Activity#attach()完成數(shù)據(jù)初始化和Context建立聯(lián)系孩等,因?yàn)锳ctivity是Context的橋接類艾君,
最后就是創(chuàng)建和關(guān)聯(lián)window,讓W(xué)indow接收的事件傳給Activity肄方,在Window的創(chuàng)建過程中會(huì)調(diào)用ViewRootImpl的performTraversals()初始化View冰垄。
6.Instrumentation#callActivityOnCreate()->Activity#performCreate()->Activity#onCreate().onCreate()中會(huì)通過Activity#setContentView()調(diào)用PhoneWindow的setContentView()
更新界面。
Intent能傳遞的數(shù)據(jù)類型
Intent可能需要跨進(jìn)程傳遞數(shù)據(jù)权她,所以傳遞的最終類型都是Parcelable或Serializable播演,Intent開放的Bundle、和Intent自身都是Parcelable對(duì)象伴奥,向Intent里傳值其實(shí)都是Bundle處理的写烤,包括CharSequence、Serializable等拾徙。
Intent能傳遞的數(shù)據(jù)大小
Intent其實(shí)是走Binder機(jī)制洲炊,內(nèi)存對(duì)Binder的mmap限制為4M以內(nèi),實(shí)際App層限制為1M~8K,所以Bitmap過大就會(huì)崩潰暂衡。
Parcelable和Serializable的區(qū)別
雖然都做序列化询微,但是實(shí)現(xiàn)方式和用途不同:
1.實(shí)現(xiàn)方式
Parcelable需要手動(dòng)實(shí)現(xiàn)writeToParcel和CREATOR的createFromParcel。
Serializable只需要實(shí)現(xiàn)Serializable接口即可狂巢,同時(shí)允許擴(kuò)展功能撑毛,比如可以利用transient關(guān)鍵字,聲明某些屬性不允許序列化唧领;可以利用serialVersionUID屬性來區(qū)分各版本數(shù)據(jù);可以利用readObject和writeObject藻雌,介入序列化和反序列化過程,這可以用來規(guī)避破壞單例的問題斩个。
2.序列化對(duì)象和讀寫
Parcelable是Android特有的胯杭,序列化為Parcel對(duì)象,可以marshall或unmarshall為byte[]數(shù)組受啥,通過操作native指針來實(shí)現(xiàn)快速讀寫和做个。
Serializable是Java通用的,序列化為Stream字節(jié)流滚局,會(huì)有大量的IO操作居暖,還會(huì)執(zhí)行反射,會(huì)產(chǎn)生很多中間變量藤肢,既有GC壓力膝但,又占用內(nèi)存,速度也慢谤草。
3.應(yīng)用場(chǎng)景
Parcelable更高效跟束,但通用性差,Parcelable通過native方法操作內(nèi)存指針丑孩,效率很高冀宴;但是Parcelable通用性差,不建議存為文件或通過網(wǎng)絡(luò)傳輸温学,雖然Parcelable也能持久化數(shù)據(jù)略贮,但是Parcelable在各android版本上差異大,在數(shù)據(jù)轉(zhuǎn)換上會(huì)有問題仗岖。
Instrumentation
是ContextImpl中的對(duì)象逃延,每個(gè)App只有一個(gè)Instrumentation對(duì)象,每個(gè)Activity通過引用Context引用這個(gè)Instrumentation對(duì)象轧拄,這是App進(jìn)程的管家揽祥,ActivityThread都是通過Instrumentation來處理創(chuàng)建、暫停Activity等處理檩电。
ListView局部刷新
ListView有時(shí)候只有一個(gè)item發(fā)生了變化拄丰,如果要只更新這1個(gè)item府树,需要三步:
1.找到item,用數(shù)據(jù)列表的index料按,減去mList.getFirstVisiblePosition()奄侠,可以判斷是否正在顯示區(qū)間內(nèi),然后用mList.get(index-firstVisiblePosition)载矿,可以找到item的View
2.取出ViewHolder垄潮,通過view.getTag(),獲取到ViewHolder
3.更新界面闷盔,直接在ViewHolder中修改item的界面
Android中App的內(nèi)存大小弯洗、largeHeap的大小
查看設(shè)備的/system/build.prop文件
dalvik.vm.heapstartsize=8m App初始大小
dalvik.vm.heapgrowthlimit=192m 普通App的上限
dalvik.vm.heapsize=512m largeHeap的App的上限
探究android:largeHeap
在onCreate中用子線程給TextView屬性賦值成功的問題
判斷主線程UI是在viewRootImpl中的checkThread進(jìn)行的,如果View還沒有繪制出來馁筐,就會(huì)先做屬性賦值,然后才會(huì)做invalidate繪制坠非,那么checkThread就是在子線程賦值之后執(zhí)行敏沉,其實(shí)還是在主線程繪制的。
所以炎码,因?yàn)樵趏nResume之后盟迟,Activity的PhoneWindow的DectorView的viewRootImpl才會(huì)被生成,所以在onCreate里賦值時(shí)不會(huì)觸發(fā)invalidate繪制潦闲。
為什么我們可以在非UI線程中更新UI
性能分析工具
一攒菠、DDMS(MAT)檢測(cè)內(nèi)存泄露;
二、TraceView跟蹤代碼執(zhí)行時(shí)間;
三歉闰、Dump UI Hierarchy for UI Atomator分析UI層級(jí)辖众;
四、Systrace追蹤系統(tǒng)中各子系統(tǒng)的運(yùn)行狀態(tài)和敬;
分別簡(jiǎn)述:
一凹炸、DDMS+MAT檢測(cè)內(nèi)存泄露;
Dalvik Debug Monitor Service是一個(gè)程序執(zhí)行查看器,能看到線程和堆棧等信息昼弟。
DDMS其實(shí)是用端口監(jiān)聽測(cè)試終端啤它,用adb建立調(diào)試器,發(fā)送指令到調(diào)試終端舱痘。
DDMS本身提供了一個(gè)簡(jiǎn)便的Heap工具查看有沒有內(nèi)存泄露現(xiàn)象变骡,通過CauseGC,檢查多次操作后內(nèi)存是否穩(wěn)定芭逝。
如果發(fā)生了內(nèi)存泄露塌碌,就收集內(nèi)存使用信息,導(dǎo)出為.hprof文件旬盯,用MAT工具去打開文件(繼續(xù)轉(zhuǎn)換一次誊爹,轉(zhuǎn)為標(biāo)準(zhǔn)hprof文件)蹬刷,詳細(xì)分析。
MAT的餅圖沒啥作用频丘,主要看Histogram办成,過濾出所有對(duì)象,列出內(nèi)存中的對(duì)象列表搂漠,檢查每個(gè)實(shí)例的Path to GC Roots迂卢,exclude所有的weak/soft引用,找到這些對(duì)象都是被哪個(gè)對(duì)象引用桐汤,從而推斷出內(nèi)存泄露的原因而克。
二、TraceView跟蹤代碼執(zhí)行時(shí)間;
TraceView是性能分析器怔毛,能查詢代碼執(zhí)行時(shí)間员萍。
1.分析具體代碼塊
首先,在代碼中插入trace標(biāo)記:
android.os.Debug.startMethodTracing("保存文件名");
android.os.Debug.stopMethodTracing();
注意要在manifest里允許讀寫文件拣度,系統(tǒng)會(huì)把數(shù)據(jù)保存到文件里/mnt/sdcard/保存文件名.trace'
然后碎绎,用Monitor工具(sdk/tools/monitor.bat)導(dǎo)入trace文件,進(jìn)行分析
2.分析App的某個(gè)操作
首先抗果,記錄操作數(shù)據(jù)筋帖,利用AS自帶的Monitors工具,點(diǎn)擊CPU一欄中秒表logo的標(biāo)記開始trace冤馏,然后操作App日麸,操作完成后,結(jié)束trace逮光。
然后代箭,分析數(shù)據(jù),TraceView提供了調(diào)用的函數(shù)涕刚、各函數(shù)的執(zhí)行時(shí)間和次數(shù)等梢卸。
正確使用Android性能分析工具——TraceView
Android系統(tǒng)性能調(diào)優(yōu)工具介紹
三、Dump View Hierarchy for UI Atomator分析UI層級(jí)副女;
DDMS里在截屏按鈕后面有個(gè)Dump View Hierarchy按鈕蛤高,可以在DDMS中刷出當(dāng)前app的頁面,選擇某個(gè)元素碑幅,就能列出其所在的UI層級(jí)等信息戴陡。
四、Systrace追蹤系統(tǒng)中各子系統(tǒng)的運(yùn)行狀態(tài)沟涨;
Systrace功能非常強(qiáng)大恤批,可以對(duì)CPU、Native進(jìn)程甚至Kernel線程采集性能數(shù)據(jù)裹赴。
在DDMS中練好設(shè)備喜庞,點(diǎn)擊最右側(cè)統(tǒng)計(jì)形狀的按鈕诀浪,設(shè)置輸出文件地址和要采集的內(nèi)容,輸出一個(gè)html文件延都,打開是張統(tǒng)計(jì)報(bào)表(只能用chrome瀏覽器打開雷猪,其他瀏覽器如Safari打開是空白)
Android性能優(yōu)化工具之Systrace
線性布局的幾個(gè)問題
線性布局中,兩個(gè)Button晰房,如何分置兩邊
利用android:layout_weight=“1”來填充剩余空間求摇,可以中間插一個(gè)透明,也可以嵌套一層殊者。
五種布局:LinearLayout与境、RelativeLayout、FrameLayout猖吴、AbsoluteLayout摔刁、TableLayout