《Android開發(fā)藝術(shù)探索》作者:任玉剛
第一章 Activity的生命周期和啟動模式
activity跳轉(zhuǎn)的時候翠肘,如果新activity采用了透明主題檐束,那么當(dāng)前activity不會回調(diào)
onStop()
onSaveInstanceState()
調(diào)用在onStop()
之前,onRestoreInstanceState()
調(diào)用在onCreate()
之后一個進程脫離四大組件而獨自運行在后臺中,很容易被系統(tǒng)殺死(從側(cè)面也理解出束倍,與用戶無交互的功能應(yīng)放在service,而不是單例中)
-
singleTask的匹配模式為:先找符合的任務(wù)棧
TaskAffinity
,再找相同的實例,另外貌夕,要啟動的activity為singleTask植旧,如果某棧中存在該實例完沪,就會把該棧整個移動到前臺棧中宽档,比如: 前臺棧存在AB實例九府,后臺棧存在CD實例婆排, 現(xiàn)在啟動D,那么就會變成前臺棧為CD,后臺棧為AB炕婶,書中圖示如下:
singleTask.png
需要注意的是,TaskAffinity
和allowTaskReparenting
結(jié)合使用的時候,情況會比較復(fù)雜,這里引用書中原話:
當(dāng)一個應(yīng)用A啟動了應(yīng)用B的某個Activity后吩坝,如何這個Activity的allowTaskReparenting屬性為true的話,那么當(dāng)應(yīng)用B被啟動后,此Activity會直接從應(yīng)用A的任務(wù)棧轉(zhuǎn)移到應(yīng)用B的任務(wù)棧中
(ps: TaskAffinity默認為應(yīng)用包名)
- intentFilter的匹配規(guī)則
action
: intent中的action只要有一個和過濾規(guī)則中的任何一個action相同即可匹配成功
category
: intent中可以沒有category酣栈,直接匹配成功妙痹,但是如果Intent中存在category那么每一個都要和過濾規(guī)則中匹配上才成功
data
: 匹配規(guī)則與action類似
注意隱式調(diào)用中,android默認會加上android.intent.categiry.DEFAULT
,所以匹配的activity的Intent-filter中必須增加該category
第二章 IPC機制
Android應(yīng)用內(nèi)開啟多進程模式只有一種方法拿霉,就是給四大組件在AndroidManifest中指定
android:process屬性
Parceable
主要用于內(nèi)存中序列化偏瓤,對于磁盤存儲以及網(wǎng)絡(luò)傳輸建議使用Serializable
所有可以在Binder中傳輸?shù)慕涌诙夹枰^承IInterface接口
binderDied() 和 onServiceDisconnected()區(qū)別女责??纺蛆?
onServiceDisconnected在客戶端的UI線程中被回調(diào),而binderDied在客戶端的Binder線程池中被回調(diào),兩者同樣可以用于重連服務(wù)的場景transact和onTransact的區(qū)別欠雌??狂打?
跨進程通信的方法:
aidl
,socket
,contenprovider
,文件共享
,intent附加extrax信息(bundle)
,messager
aidl中,客服端調(diào)用遠程服務(wù)的方法,被調(diào)用的方法運行在服務(wù)端的Binder線程池中,相反服務(wù)端調(diào)客戶端也一樣
aidl中玻淑,接口的注冊和解注冊使用RemoteCallbackList實現(xiàn)
綁定binder的權(quán)限驗證方式:
permission
,packageName
多service的情況,可以使用binder連接池處理
第三章 View的事件體系
getX()
和getY()
: 返回相對于當(dāng)前View左上角的x和y坐標(biāo)
getRaw()Y
和getRawY()
:返回相對于手機屏幕左上角的x和y坐標(biāo)TouchSlop為系統(tǒng)所能識別的最小滑動距離,即小于這個數(shù)值的距離不認為為滑動位喂,獲取方式:
ViewConfiguration.get(getContext()).getScaledTouchSlop()
-
mScrollX/mScrollY
指的是view的邊緣和view內(nèi)容邊緣的滑動距離收津,這個通過下面圖來理解就好
mScrollX和mScrollY的變換規(guī)律示意.png requestDisallowInterceptTouchEvent
方法可以在子元素中干預(yù)父元素的事件分發(fā)過程,但是ACTION_DOWN
事件除外觸摸事件分發(fā)機制圖
第四章 View的工作原理
measureSpec
不是唯一由LayoutParams
決定的,LayoutParams需要和父容器一起才能決定View的MeasureSpec串结,從而進一步?jīng)Q定View的A寬/高view最終的大小是在layout階段確定的(參考第五點)
一個比較好的習(xí)慣是在onLayout方法中去獲取View的測量寬/高或者最終寬/高
獲取view測量的寬/高方法
Activity/View#onWinndowFocusChanged
view.post(runnable)
VieTreeObserver
getMeasuredWidth和getWidth的區(qū)別拗慨?
getMeasuredWidth
:是測量時賦值
getWidth
:是布局時賦值(右上角左邊減去左上角左邊)
getMeasuredWidth
和getWidth
不一定相等view有一個特殊的方法setWillNotDraw,該方法是用于對于沒有繪制的view進行優(yōu)化的奉芦,如果明確知道一個viewgroup需要調(diào)用onDraw的時候,需要顯示的關(guān)閉這個標(biāo)記位
7 自定義view須知
讓View支持wrap_content
如果有必要剧蹂,讓你的View支持padding
盡量不要在View中使用Handler声功,除非必要情況
View中如果有線程/動畫,需要及時停止宠叼,參考View#onDeteachedFromWindow
View帶有滑動嵌套情形時先巴,需要處理好滑動沖突
第五章 理解RemoteViews
-
PendingIntent
的匹配規(guī)則:如果兩個PendingIntent它們內(nèi)部的Intent相同并且requestCode也相同,那么這兩個PendingIntent就是相同的,其中Intent的匹配規(guī)則是ComponentName和intent-filter都相同冒冬,排除Extras
第六章 Android的Drawable
- 一般來說drawable是沒有大小概念的伸蚯,但他可以設(shè)置固有寬/高,并通過
getIntrinsicWidth
和getIntrinsicHeight
這兩個方法獲取
第七章 Android動畫深入分析
View動畫中的shareInterpoliator屬性表示: 動畫集合是否共享一個插值器
activity的切換效果可以在
startActivity(intent)/finish()
之后調(diào)用overridePendingTransition(int enterAnim,int exitAnim)
使用動畫的過程中建議開啟硬件加速简烤,這樣會提高動畫的流暢性
擴展:
補間動畫的實現(xiàn)原理:
1.調(diào)用view的startAnimation會執(zhí)行invalidate(true)剂邮,然后就會遍歷整個樹圖,然后找到viewrootimpl,接著執(zhí)行它的performTraversals横侦,這個就在正常view繪制的三大流程入口
2.其中在view繪制的時候調(diào)用的是draw(三個參數(shù)),里面執(zhí)行applyLegacyAnimation挥萌,該方法最終會執(zhí)行到子類的applyTransformation方法,就是具體的矩陣變換算法中枉侧,另外還會返回一個動畫是否結(jié)束的標(biāo)志引瀑,如果沒有結(jié)束則重新走invalidate()繼續(xù)繪制視圖
3.applyTransformation實際操作的對象是canvas,而不是view中的具體屬性值碍现,所以補間動畫不會改變view的真正大小和位置没炒,只是對他的canvas做矩陣變換
第八章 理解Window和WindowManager
window有三種類型:
應(yīng)用window: 層級為1~99
子window:層級為1000~1999
系統(tǒng)wind: 層級為2000~2999window進行添加view,更新view营罢,刪除view的操作實際是通過windowManager實現(xiàn)的,而windownManager又委托給WindowManagerGlobal來進行屑柔,golbal主要分如下幾步來實現(xiàn):
檢查參數(shù)是否合法,如果是子window那么還需要調(diào)整一些布局參數(shù)
創(chuàng)建viewrootimpl并將view添加到列表中(其內(nèi)部有 mViews蛙讥,mRoots,mParams等集合锯蛀,分別為所有window對應(yīng)的view,所有window對應(yīng)的viewrootimpl次慢,所有window的布局參數(shù))
最后通過viewrootimpl來更新界面并完成window的添加旁涤,其實際是通過WindowSession訪問WindowManagerService進行window的添加-
window添加流程時序圖
image.png
第九章 四大組件的工作工程
看得云里霧里
第十章 Android的消息機制
ActivityThread也就是UI線程翔曲,在創(chuàng)建的時候就會初始化Looper,這也是在主線程中默認可以使用Handler的原因
ThreadLocal是一個線程內(nèi)部的數(shù)據(jù)存儲類劈愚,不同線程中的數(shù)據(jù)相互獨立互不干擾
handler處理消息機制主要是: handler向Messagequeue插入了一條消息瞳遍,Messagequeue的next方法會返回這條消息給looper,looper收到消息后就開始處理菌羽,最后又交回給handler處理掠械,即handler的dispatchMessage方法會被調(diào)用
第十一章 Android的線程和線程池
1.ThreadPoolExecutor構(gòu)造方法的參數(shù)意義:
corePoolSize
: 最大核心線程數(shù),一直存活注祖,但是如果設(shè)置了allowCoreThreadTimeOut為true猾蒂,會有超時策略
maximumPoolSize
:線程池所能容納的最大線程數(shù)
keepAliveTime
: 非核心線程閑置時的超時時長,allowCoreThreadTimeOut為true時,核心線程數(shù)也會被回收
unit
:超時時間單位
workQueue
: 任務(wù)隊列大小
threadFactor
:線程共創(chuàng)是晨,為線程池提供創(chuàng)建新線程的功能
常用四類線程池
FixedThreadPool
: 快速響應(yīng)外界的請求
CacgedTgreadPool
:適合執(zhí)行大量的耗時較少的任務(wù)
ScheduledThreadPool
: 主要用于執(zhí)行定時任務(wù)和具有固定周期的重復(fù)任務(wù)
SingleThreadExecutor
:確保所有的任務(wù)都在同一個線程中按順序執(zhí)行AsyncTask實際是封裝了Thread和Handler,IntentService實際是封裝了HandlerThread和Handler
第十二章 Bitmap的加載和Cache
- 采用BitmapFactory.Onptions來高效加載Bitmap肚菠,其中涉及的參數(shù):
inJustDecodeBounds
: 設(shè)為true時,BitmapFactory只會解析圖片的原始寬/高信息罩缴,并不會真正地加載圖片蚊逢,所以這個操作是輕量級的,通常用于需要修改inSampleSize(采樣率)的使用
inSampleSize
: 采樣率箫章,小于1無效烙荷,盡量使用2的指數(shù),bitmap的像素/內(nèi)存占用縮放比例為 1/(inSampleSize的2次方)