【讀書筆記】《Android開發(fā)藝術(shù)探索》

這本書對初學(xué)者來說還是比較有深度的,知識覆蓋面也比較廣
雖然可能講解的重點不一定都是你想看到的,但是對于安卓開發(fā)進(jìn)階來說是一本不錯的總體概覽書籍,能夠get到一些實用的技能點

前后用了一個星期的時間來看,總體來說比較有參考價值的,閱讀起來也沒有太大難度

評價:三星半


鏈接、圖片、筆記文本

下面是印象筆記公開鏈接、XMind思維導(dǎo)圖圖片與文字

EverNote鏈接

圖片:

Android開發(fā)藝術(shù).png

文字:

Android 開發(fā)藝術(shù)探索
1 1 Activity生命周期和啟動模式
1.1 生命周期
1.1.1 典型周期
1.1.1.1 onStart
1.1.1.1.1 Activity已經(jīng)可見,但是沒有出現(xiàn)在前臺
1.1.1.2 onResume
1.1.1.2.1 Activity可見,出現(xiàn)在前臺并且開始活動
1.1.1.3 onPause
1.1.1.3.1 可以做一些存儲數(shù)據(jù)、停止動畫等工作,但是不能太耗時
1.1.1.4 onStop
1.1.1.4.1 可以做一些重量級工作,但也不能太耗時
1.1.1.4.2 如果新Activity采用了透明主題,那么當(dāng)前Activity不會回調(diào)onStop
1.1.1.5 從Activity A切換到Activity B
1.1.1.5.1 A先執(zhí)行onPause,B再執(zhí)行onCreate-onStart-onResume,最后才是A執(zhí)行onStop
1.1.2 異常周期
1.1.2.1 被系統(tǒng)回收
1.1.2.2 當(dāng)Activity并不是由我主動點擊back鍵而喪失焦點時,onSaveInstanceState方法就一定會調(diào)用
1.1.2.2.1 google工程師們對onSaveInstanceState如此設(shè)計就是讓其完成對一些臨時的、非永久數(shù)據(jù)存儲并進(jìn)行恢復(fù)
1.1.2.2.2 Android的View本身自己就實現(xiàn)了onSaveInstanceState方法,這些控件自己就具有保存臨時數(shù)據(jù)和恢復(fù)臨時數(shù)據(jù)的能力
1.1.2.2.2.1 值得一提的是,只有當(dāng)你給這個wiget在xml中指定id時,它才具有保存數(shù)據(jù)并且恢復(fù)的能力,并且不同的wiget還不能共用這個id,否則會出現(xiàn)數(shù)據(jù)覆蓋的情況。
1.1.2.2.3 onRestoreInstanceState一旦被調(diào)用,其參數(shù)Bundle savedInstanceState一定是有值的
1.1.2.3 資源不足導(dǎo)致低優(yōu)先級的Activity被殺死
1.1.2.4 Configuration改變導(dǎo)致的銷毀重建
1.1.2.4.1 通過configChanges配置
1.2 啟動模式
1.2.1 Activity的LaunchMode
1.2.1.1 standard
1.2.1.1.1 這種模式的Activity默認(rèn)會進(jìn)入啟動它的Activity所屬的任務(wù)棧中,但諸如ApplicationContext等Context并沒有所謂的任務(wù)棧,需要在啟動時添加FLAG_ACTIVITY_NEW_TASK,這樣啟動時就會為它創(chuàng)建一個新的任務(wù)棧,此時其實是以singleTask模式啟動的
1.2.1.2 singleTop
1.2.1.3 singleTask
1.2.1.3.1 taskAffinity屬性,配合singleTask使用,指定Activity運行的任務(wù)棧名,是一個字符串,Activity默認(rèn)的棧名是Application的包名
1.2.1.3.2 singleTask模式的Activity切換到棧頂會導(dǎo)致在它之上的棧內(nèi)的Activity出棧
1.2.1.4 singleInstance
1.2.2 Activity的Flags
1.2.2.1 FLAG_ACTIVITY_NEW_TASK
1.2.2.2 FLAG_ACTIVITY_SINGLE_TOP
1.2.2.3 FLAG_ACTIVITY_CLEAR_TOP
1.2.2.3.1 帶此標(biāo)記位啟動Activity,啟動它時,在同一棧中所有位于它上面的Activity都要出棧
1.2.2.3.2 一般會和singleTask啟動模式一起出現(xiàn),如果Activity已經(jīng)創(chuàng)建,則調(diào)用onNewIntent
1.2.2.4 FLAG_ACTIVITY_EXCLUDE_FROME_RECENTS
1.2.2.4.1 相當(dāng)于xml中聲明 android:exludeFromRecents="true"
1.2.2.4.2 Activity不會出現(xiàn)在歷史Activity列表中
1.2.3 IntentFilter匹配規(guī)則
1.2.3.1 為了匹配過濾列表,需要同時匹配過濾列表中的action、category、data信息,否則匹配失敗。只有一個Intent同時匹配action、category、data才算完全匹配,只有完全匹配才能啟動目標(biāo)Activity。
1.2.3.2 一個Activity中可以有多個intent-filter,一個Intent只要能匹配任何一組intent-filter即可成功啟動對應(yīng)的Activity
1.2.3.3 具體細(xì)則
1.2.3.3.1 action匹配規(guī)則
1.2.3.3.1.1 字符必須完全相同,一個過濾規(guī)則中可以有多個action,只要Intent的action能夠與其中任意一個相同即可匹配成功
1.2.3.3.1.2 必須含有action項,可以有多個,只要其中一項能在intent-filter中找到匹配項就行
1.2.3.3.2 category匹配規(guī)則
1.2.3.3.2.1 可以沒有,如果有,則必須全部被包含在intent-filter中
1.2.3.3.2.2 startActivity時默認(rèn)含有android.intent.category.DEFAULT這個category
1.2.3.3.3 data匹配規(guī)則
1.2.3.3.3.1 與action類似
1.2.3.3.3.2 由兩部分組成 mimeType和URI
1.2.3.3.3.2.1 URI
1.2.3.3.3.2.1.1 <scheme>://<host>:<port>/[<path>][<pathPrefix>][<pathPattern>]
1.2.3.3.3.3 如果為intent指定完整的data,必須調(diào)用setDataAndType,不能先setData再setType,因為這兩個方法彼此會清楚對方的值
2 2. IPC機(jī)制
2.1 簡介
2.1.1 縮寫: Inter-Process Communication 進(jìn)程間通信或者跨進(jìn)程通信
2.1.2 進(jìn)程與線程
2.1.2.1 線程是CPU調(diào)度的最小單元,線程是一種有限的系統(tǒng)資源
2.1.2.2 進(jìn)程一般指一個執(zhí)行單元,在PC或移動設(shè)備上指一個程序或者一個應(yīng)用。
2.1.2.3 一個進(jìn)程中可以只有一個線程,即主線程;在Android里的主線程也叫UI線程,由此引出ANR,線程
2.1.3 不是Android獨有,Linux上可以通過命名管道、共享內(nèi)存、信號量等來進(jìn)行進(jìn)程間通信。
2.1.4 Android中最有特色的進(jìn)程間通信方式就是Binder,也支持socket
2.2 Android中的多進(jìn)程模式
2.2.1 使用多進(jìn)程的方法:在AndroidMenifest中指定android:process屬性
2.2.1.1 以“:”開頭的進(jìn)程屬于當(dāng)前進(jìn)程的私有進(jìn)程,否則為全局進(jìn)程,其他應(yīng)用通過ShareUID方式可以和它運行在同一進(jìn)程中
2.2.2 數(shù)據(jù)共享的問題
2.2.3 引發(fā)的問題
2.2.3.1 靜態(tài)成員和單例模式完全失敗
2.2.3.1.1 運行在不同進(jìn)程中的四大組件,想通過內(nèi)存來共享數(shù)據(jù)都會失敗
2.2.3.2 線程同步機(jī)制完全失效
2.2.3.3 SharedPreference可靠性下降
2.2.3.4 Application會多次創(chuàng)建
2.3 基礎(chǔ)概念
2.3.1 Serializable接口
2.3.1.1 是Java的一個序列化接口,只需在類中聲明serialVersionUID標(biāo)識即可自動實現(xiàn)默認(rèn)序列化過程
2.3.1.1.1 標(biāo)識用以輔助序列化與反序列化過程,反序列化時會檢查和當(dāng)前類是否一致(可能類被修改了,如添加了成員)
2.3.1.2 Serializable使用簡單,但是含有大量IO操作,開銷大
2.3.2 Parcelable
2.3.2.1 只要實現(xiàn)這個接口,一個類的對象就可以實現(xiàn)序列化,并且可以通過Intent和Binder傳遞
2.3.2.2 系統(tǒng)已經(jīng)為我們提供了許多實現(xiàn)了Parcelable接口的類,如Intent、Bundle、Bitmap,同時List和Map也可以序列化
2.3.2.3 Parcelable稍顯麻煩,但是效率很高
2.3.3 Binder
2.3.3.1 Android特有,可以理解為虛擬的物理設(shè)備
2.3.3.2 應(yīng)用層來說,是客戶端和服務(wù)端進(jìn)行通信的媒介
2.3.3.3 主要用在Service中,包括AIDL和Messenger
2.3.3.4 手動實現(xiàn)Binder的步驟
2.3.3.4.1 聲明一個AIDL接口,只需繼承IInterface(只有一個asBinder方法)
2.3.3.4.2 實現(xiàn)Stub類和Stub類中的Proxy代理類
2.3.3.5 linkToDeath與unlinkToDeath
2.4 Android中的IPC
2.4.1 方式
2.4.1.1 Intent中添加extras
2.4.1.2 Binder跨進(jìn)程通信
2.4.1.3 ContentProvider支持跨進(jìn)程
2.4.1.4 網(wǎng)絡(luò)通信,如socket
2.4.1.5 文件共享
2.4.1.5.1 并發(fā)問題
2.4.1.5.2 SharedPreference雖然本質(zhì)也也是文件,但系統(tǒng)對它的讀寫有一定的緩存策略,所以不在進(jìn)程間通信時使用
2.4.2 使用Messenger
2.4.2.1 一種輕量級的IPC方案,底層實現(xiàn)是AIDL
2.4.2.2 使用方法簡單,它對AIDL做了封裝
2.4.2.3 由于一次處理一個請求,因此在服務(wù)端我們不用考慮線程同步的問題(服務(wù)端不存在并發(fā)執(zhí)行的情況)
2.4.2.4 實現(xiàn)步驟
2.4.2.4.1 服務(wù)端進(jìn)程
2.4.2.4.2 客戶端進(jìn)程
2.4.3 AIDL
2.4.3.1 服務(wù)端
2.4.3.1.1 創(chuàng)建Service
2.4.3.1.2 創(chuàng)建AIDL文件,將暴露給客戶端的接口在這個AIDL文件中聲明
2.4.3.1.3 在Service中實現(xiàn)這個接口
2.4.3.2 客戶端
2.4.3.2.1 綁定服務(wù)端Service
2.4.3.2.2 將服務(wù)端返回的Binder對象轉(zhuǎn)換成AIDL接口所屬的類型
2.4.3.2.3 調(diào)用AIDL中的方法
2.4.3.3 AIDL接口的創(chuàng)建
2.4.3.3.1 支持的數(shù)據(jù)類型
2.4.3.3.1.1 基本數(shù)據(jù)類型
2.4.3.3.1.2 String CharSequence
2.4.3.3.1.3 ArrayList
2.4.3.3.1.4 HashMap
2.4.3.3.1.5 Parcelable
2.4.3.3.1.6 AIDL
2.4.4 ContentProvider
2.4.4.1 繼承ContentProvider,實現(xiàn)六個方法:onCreate、query、update、insert、delete和getType
2.4.4.1.1 onCreate用來創(chuàng)建
2.4.4.1.1.1 在主線程中,不能進(jìn)行耗時操作
2.4.4.1.2 getType用以返回MIME類型,如果返回null或者 /表示不關(guān)注
2.4.4.2 底層看來來像一個SQLite數(shù)據(jù)庫,但其實對底層數(shù)據(jù)儲存沒有任何要求,可以使用普通文件,可以采用內(nèi)存中的一個對象來進(jìn)行數(shù)據(jù)存儲
2.4.4.3 注冊自定義的ContentProvider
2.4.4.3.1 android:authorities是ContentProvider的唯一表示,通過這個屬性外部應(yīng)用就可以訪問我們的ContentProvider了,所以必須保證authorities唯一(可以加上包名前綴)
2.4.5 Sockete
2.4.6 Binder連接池
2.4.6.1 可以極大的提高AIDL的開發(fā)效率,并且可以避免大量的Service創(chuàng)建
3 3. View事件體系
3.1 基礎(chǔ)
3.1.1 位置參數(shù)
3.1.1.1 left、right、top、bottom
3.1.1.2 3.0之后添加了x、y、translationX、translationY
3.1.2 MotionEvent與TouchSlop
3.1.3 VelocityTracker、GestureDetector、Scroller
3.1.3.1 獲取速度前必須先計算速度
3.1.3.2 這里的速度是指一段時間內(nèi)手指所滑過的像素
3.1.3.3 不需要使用時,需要調(diào)用clear方法來重置并回收內(nèi)存
3.2 View的滑動
3.2.1 scrollTo、scrollBy
3.2.1.1 只能滑動View的內(nèi)容,并不能滑動View本身
3.2.2 使用動畫
3.2.2.1 將fillAfter屬性設(shè)置為true可以保持動畫結(jié)束后的view效果(但是view的四個頂點坐標(biāo)并沒有發(fā)生變化)
3.2.3 改變布局參數(shù)
3.2.4 比較: scrollTo/ScrollBy操作簡單,適合對View內(nèi)容的滑動 動畫:操作簡單,主要適用于沒有交互的View和實現(xiàn)復(fù)雜的動畫效果 改變布局參數(shù):操作相對復(fù)雜,適用于有交互的View
3.2.5 eg:
3.2.5.1 具有跟手滑動效果的View:只需要重寫onTouchEvent方法并處理ACTION_MOVE事件,根據(jù)兩次滑動之間的距離就可以實現(xiàn)它的滑動。為了實現(xiàn)全屏滑動,需要采用動畫的方式來實現(xiàn)(原書P134)
3.3 彈性滑動
3.3.1 使用Scroller
3.3.1.1 配合View的computeScroll方法完成,對View沒有絲毫的引用,內(nèi)部也不含有計時器
3.3.2 通過動畫,一幀一幀地更新,設(shè)置動畫的updateListener實現(xiàn)
3.3.3 使用延時策略
3.3.3.1 使用Handler或View的postDelay方法
3.4 View的事件分發(fā)機(jī)制
3.4.1 傳遞規(guī)則
3.4.1.1 dispatchTouchEvent
3.4.1.1.1 用來進(jìn)行事件分發(fā)
3.4.1.2 onInterceptTouchEvent
3.4.1.2.1 用來判斷是否攔截某個事件
3.4.1.3 onTouchEvent
3.4.1.3.1 dispatchTouchEvent中調(diào)用,處理點擊事件,返回結(jié)果表示是否消耗當(dāng)前事件
3.4.1.4 關(guān)系偽代碼
3.4.1.4.1 public boolean dispatchTouchEvent(MotionEvent ev){ boolean consume = false; if(onInterceptTouchEvent(ev)){ consume = onTouchEvent(ev); }else{ consume = child.dispatchTouchEvent(ev); } return consume; }
3.4.1.5 結(jié)論
3.4.1.5.1 同一個事件序列內(nèi)的事件不能分別由兩個View同時處理(不包含特殊處理)
3.4.1.5.2 某個View一旦決定攔截,那么這一事件序列都只能由它來處理,并且它的onInterceptTouchEvent不會再被調(diào)用
3.4.1.5.3 如果View不消耗除ACTION_DOWN以外的其他事件,那么這個點擊事件會小時,父元素的onTouchEvent并不會被調(diào)用,最終這些消耗的點擊事件會傳遞給Activity處理
3.4.1.5.4 ViewGroup默認(rèn)不攔截任何事件
3.4.1.5.5 View沒有onInterceptTouchEvent方法
3.4.1.5.6 View的onTouchEvent默認(rèn)都會消耗事件(返回true),除非是不可點擊的(clickable和longClickable同時為false)
3.4.1.5.7 View的enable屬性不影響onTouchEvent默認(rèn)返回值。哪怕一個View是disable狀態(tài),只要它的clickable或者longclickable有一個為true,那么它的onTouchEvent就返回true
4 4. View工作原理
4.1 ViewRoot、DecorView
4.1.1 DecorView作為頂級View,一般會包含一個豎直方向的LinearLayout
4.1.1.1 一個是titlebar,一個是content,這也是setContentView所設(shè)置的對象
4.1.2 View層的事件都先經(jīng)過DecorView,然后才傳遞給我們的View
4.2 MeasureSpec
4.2.1 一個32位的int值,高2位為SpecMode,低30位代表SpecSize
4.3 View工作流程
4.3.1 主要指measure、layout、draw
4.3.1.1 如何在Activity中獲取view的寬高?
4.3.1.1.1 Activity#onWindowFocusChanged
4.3.1.1.2 view.post(runnable)
4.3.1.1.3 ViewTreeObserver
4.3.1.1.4 view.measure(int windthMeasureSpec, int heightMeasureSpec)
4.3.1.2 ViewGroup會逐個measure子view
4.3.2 layout過程
4.3.2.1 通過setFrame去設(shè)置子元素的四個頂點位置
4.3.3 draw過程
4.3.3.1 View繪制過程是通過dispatchDraw來實現(xiàn)的,dispatchDraw會遍歷調(diào)用所有字元素的draw
4.4 自定義View
4.4.1 分類
4.4.1.1 onDraw
4.4.1.2 繼承ViewGroup
4.4.1.3 繼承特定View
4.4.1.4 繼承特定ViewGroup
4.4.2 須知
4.4.2.1 讓View支持wrap_content
4.4.2.2 如有必要,讓其支持padding
4.4.2.2.1 在onDraw中取padding值,加入繪制參數(shù)計算
4.4.2.3 盡量不用Handler
4.4.2.4 View中如果有線程或動畫,需要及時停止,View#onDetachFromWindow
4.4.2.5 View帶有滑動嵌套時,處理好滑動沖突
4.4.3 xml屬性擴(kuò)展
4.4.3.1 1. values目錄下創(chuàng)建xml
4.4.3.1.1 eg: <declare-styleable name="CircleView"> <attr name="circle_color" format="color"> <.declare-syleable>
4.4.3.2 2. 在View的構(gòu)造方法中解析自定義屬性的值并處理
4.4.3.2.1 eg: TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleView); mColor = a.getColor(R.styleable.CircleView_circle_color, Color.RED); a.recycle();
4.4.3.3 3. 在布局文件中使用自定義屬性
4.4.3.3.1 s
5 5. RemoteViews
5.1 應(yīng)用
5.1.1 通知欄
5.1.1.1 通過RemoteViews提供的方法來更新視圖
5.1.2 桌面小部件
5.1.2.1 定義小部件界面
5.1.2.2 定義配置信息
5.1.2.3 定義實現(xiàn)類
5.1.2.4 在androidManifest中聲明小部件
5.1.3 PendingIntent
5.1.3.1 內(nèi)部的Intent相同,并且requestCode也相同即為相同;其中intent相同只需要ComponentName和intent-filter相同
5.2 內(nèi)部機(jī)制
5.2.1 系統(tǒng)并沒有通過binder去支持所有的view操作,僅支持了少量的view(TextView,ImageView等),這是出于效率考慮
5.2.2 提供了一個Action概念,Action實現(xiàn)了Parcelable接口,代表一個View操作;將這些actions放到ArrayList中,統(tǒng)一通過Binder進(jìn)行通信,提高IPC效率
6 6. Drawable
6.1 分類
6.1.1 BitmapDrawable
6.1.1.1 android:antialias 抗鋸齒
6.1.1.2 android:dither 抖動效果,開啟這個選項可以讓高質(zhì)量的圖片在低質(zhì)量的屏幕上還能保持較好的顯示效果
6.1.1.3 android:filter 是否開啟過濾效果。當(dāng)圖片尺寸被拉伸或者壓縮時,開啟過濾效果可以保持較好的顯示效果
6.1.1.4 android:tileMode 平鋪模式。有 disable|clamp|repeat|mirror幾個選項,開啟平鋪模式之后gravity屬性會被忽略
6.1.2 ShapeDrawable
6.1.2.1 可以通過純色構(gòu)造,也可以是具有漸變效果的圖形
6.1.2.2 android:shape —— rectangle/oval/line/ring
6.1.2.2.1 line 和ring兩個選項必須通過stroke標(biāo)簽來指定線的寬度和顏色等信息
6.1.2.3 <corners>表示shape 的四個角度,只使用于矩形shape,這里的角度是指圓角程度,用px表示
6.1.2.4 <gradient> 與solid標(biāo)簽是相互排斥的,其中solid表示純色填充,而gradient則表示漸變效果
6.1.3 LayerDrawable
6.1.3.1 對應(yīng)的標(biāo)簽是 <layer-list>,它表示一種層次化的Drawable集合,通過將不同的Drawable放置在不同的層上面從而達(dá)到一種疊加后的效果
6.1.4 StateListDrawable
6.1.4.1 對應(yīng)的標(biāo)簽是<selector>,也是表示Drawable集合,每個Drawable都對應(yīng)著View的一種狀態(tài)
6.1.5 LevelListDrawable
6.1.5.1 <level-list>,集合中的每個Drawable都有一個等級的概念(level 0~10000)
6.1.5.2 如果被用來作為ImageView的前景Drawable,那么還可以通過ImageView的setImageLevel方法來切換Drawable
6.1.6 TransitionDrawable
6.1.6.1 <transition>,用于實現(xiàn)兩個Drawable之間的淡入淡出效果
6.1.6.2 可以用作View的背景,也可以在ImageView中直接作為Drawable來使用
6.1.7 InsertDrawable
6.1.7.1 <insert>,可以將其他Drawable內(nèi)嵌到自身當(dāng)中,當(dāng)一個View希望自己的背景比自己的實際區(qū)域小時可以采用
6.1.8 ScaleDrawable
6.1.8.1 <scale>,
6.1.9 ClipDrawable
6.1.9.1 <clip>,根據(jù)自己當(dāng)前l(fā)evel來裁剪另一個Drawable
6.2 自定義Drawable
6.2.1 通常我們很少自定義Drawable,因為自定義的Drawable無法再xml中使用
7 7. 動畫
7.1 View動畫
7.1.1 四個子類:TranslateAnimation、ScaleAnimation、RotateAnimation、AlphaAnimation
7.1.1.1 可以通過代碼設(shè)置,也可用XML
7.1.1.2 既可以是單個動畫,也可以由一系列動畫組成
7.1.2 自定義View動畫
7.1.2.1 方式:繼承Animation類,重寫initialize和applyTransformation方法,在initialize中做一些初始化工作,在applyTransformation中進(jìn)行相應(yīng)的矩陣變換即可,很多時候需要采用Camera來簡化矩陣變換過程
7.1.3 幀動畫
7.1.3.1 AnimationDrawable 順序播放一組預(yù)先定義好的圖片,類似于電影播放
7.1.3.2 幀動畫使用比較簡單,但是比較容易引起OOM,在使用時應(yīng)盡量避免使用過多尺寸較大的圖片
7.2 View動畫的特殊使用場景
7.2.1 LayoutAnimation
7.2.1.1 作用于ViewGroup,為ViewGroup指定一個動畫,這樣當(dāng)它的子元素出場時都會具有這種動畫效果
7.2.1.2 步驟
7.2.1.2.1 定義LayoutAnimation
7.2.1.2.2 為子元素指定具體入場動畫
7.2.1.2.3 為ViewGroup指定android:layoutAnimation屬性
7.2.1.2.3.1 對ListView來說,這樣Listview的item就具有出場動畫了
7.2.1.2.3.2 除了xml指定,還可以通過LayoutAnimationController來實現(xiàn)
7.2.2 Activity切換效果
7.3 屬性動畫
7.3.1 簡介: ValueAnimation、ObjectAnimation、AnimatorSet
7.3.2 使用屬性動畫
7.3.2.1 屬性動畫從API 11 才有,可以使用nineoldandroids來兼容老版
7.3.2.2 可以利用代碼、XML形式實現(xiàn) 一般會采用代碼形式
7.3.3 理解插值器和估值器
7.3.4 屬性動畫的監(jiān)聽器
7.3.4.1 主要接口:AnimatorUpdateListener和AnimatorListener
7.3.4.2 AnimatorUpdateListener比較特殊,它會對整個動畫過程進(jìn)行監(jiān)聽,動畫每播放一幀,onAnimationUpdate就會被調(diào)用一次
7.3.5 對任意屬性做動畫
7.3.5.1 我們對object的屬性abc做動畫,如果想讓動畫生效,要同時滿足兩個條件:
7.3.5.1.1 object必須提供setAbc方法,如果動畫的時候沒有傳遞初始值,那么還要提供getAbc方法
7.3.5.1.2 object的setAbc對屬性abc所做的改變必須能夠通過某種方法反映出來,比如帶來UI的改變之類
7.3.5.2 如果無法滿足條件
7.3.5.2.1 1. 給你的對象加上get和set方法,如果有權(quán)限的話
7.3.5.2.2 2. 用一個類來包裝原始對象,間接為其提供get和set方法
7.3.5.2.3 3. 采用ValueAnimator,監(jiān)聽動畫過程,自己實現(xiàn)屬性的改變
7.3.6 工作原理
7.4 使用動畫的注意事項
7.4.1 OOM
7.4.2 memory leak
7.4.2.1 無限循環(huán)動畫需要在Activity退出時及時停止,否則將導(dǎo)致Activity無法釋放從而造成內(nèi)存泄露
7.4.2.2 兼容性問題
7.4.2.3 View動畫的問題
7.4.2.3.1 View動畫是對View的影像做動畫,不不是真正改變View的狀態(tài),有時會出現(xiàn)動畫完成后View無法隱藏的現(xiàn)象,即setVisiblity(View.GONE)失效了,這時只要調(diào)用View.clearAnimation()清除View動畫即可解決此問題
7.4.2.4 不要使用px
7.4.2.5 動畫元素交互
7.4.2.5.1 新位置將無法觸發(fā)單擊事件
7.4.2.6 硬件加速
8 8. Window和WindowManager
8.1 簡介
8.1.1 Flags參數(shù)、Type參數(shù)
8.1.2 windowManger提供三個常用方法:添加view、更新View、刪除View
8.2 Window的內(nèi)部機(jī)制
8.2.1 Window添加
8.2.1.1 使用到了橋接模式,內(nèi)部使用WindowManagerGlobal統(tǒng)一委托實現(xiàn)
8.2.1.2 添加過程其實是一次IPC調(diào)用,binder模式
8.2.2 Window刪除
8.2.3 Window 更新
8.3 Window的創(chuàng)建過程
8.3.1 Activity的Window創(chuàng)建
8.3.1.1 Window對象的創(chuàng)建是通過PolicyManager的makeNewWindow實現(xiàn)的
8.3.1.1.1 Window的具體實現(xiàn)類是PhoneWindow
8.3.1.2 步驟
8.3.1.2.1 如果沒有DecorView,創(chuàng)建它
8.3.1.2.2 將View添加到DecorView的mContentParent中
8.3.1.2.3 回調(diào)Activity的onContentChanged方法通知Activity視圖已經(jīng)發(fā)生改變
8.3.2 Dialog的Window創(chuàng)建
8.3.2.1 創(chuàng)建Window
8.3.2.2 初始化DecorView并將Dialog視圖添加到DecorView中
8.3.2.3 將DecorView添加到Window中并顯示
8.3.2.3.1 Dialog的context必須使用Activity的,不能使用Application的context;一定要使用的話可以設(shè)定Window類型,聲明alert權(quán)限(見書本P310)
8.3.3 Toast的Window創(chuàng)建
9 9. 四大組件工作過程
9.1 運行狀態(tài)
9.1.1 除BroadcastReceiver外,其他三個都要在Manifest中注冊
9.2 Activity的工作過程
9.2.1 performLauncherActivity最終完成Activity對象的創(chuàng)建和啟動過程,并且ActivityThread通過handleResumeActivity方法來調(diào)用被啟動的Activity
9.2.1.1 1. 從ActivityClientRecord中獲取待啟動的Activity組件信息
9.2.1.2 2. 通過instrumentation的newActivity方法使用類加載器創(chuàng)建Activity對象
9.2.1.3 3. 通過LoadedApk的makeApplication方法來嘗試創(chuàng)建Application對象
9.2.1.4 4. 創(chuàng)建ContextImpl對象并通過Activity的attach方法來完成一些重要數(shù)據(jù)的初始化
9.2.1.5 5. 調(diào)用Activity的onCreate方法
9.3 Service工作過程
9.3.1 分類
9.3.1.1 啟動狀態(tài),用于執(zhí)行后臺計算任務(wù)
9.3.1.2 綁定狀態(tài),用戶其它組件和Service交互
9.3.2 啟動過程
9.3.2.1 利用ActivityManagerService
9.3.3 綁定過程
9.3.3.1 當(dāng)多次綁定同一個Service時,onBind方法只會執(zhí)行一次,除非Service被終止
9.4 BroadcastReceiver工作過程
9.4.1 注冊
9.4.2 發(fā)送接受
9.5 ContentProvider
9.5.1 onCreate要先于Application的onCreate執(zhí)行,這在四大組件中是比較少見的現(xiàn)象
9.5.2 步驟
9.5.2.1 1. 創(chuàng)建ContextImpl和Instrumentation
9.5.2.2 2. 創(chuàng)建Application
9.5.2.3 3. 啟動當(dāng)前進(jìn)程的ContentProvider并調(diào)用其onCreate方法
9.5.2.4 4. 調(diào)用Application的onCreate方法
10 10. Android消息機(jī)制
10.1 概述
10.1.1 MessageQueue內(nèi)部是單鏈表
10.1.2 Handler創(chuàng)建時會采用當(dāng)前線程的Looper來構(gòu)建內(nèi)部消息循環(huán)系統(tǒng)
10.2 消息機(jī)制分析
10.2.1 ThreadLocal
10.2.1.1 是一個線程內(nèi)部的數(shù)據(jù)存儲類,通過它可以在指定的線程中存儲數(shù)據(jù),數(shù)據(jù)存儲后只有在指定線程中可以獲取到數(shù)據(jù)
10.2.1.2 若數(shù)據(jù)以線程為作用域且不同線程具有不同的數(shù)據(jù)副本時,可以考慮采用ThreadLocal
10.2.1.3 另一個使用場景是復(fù)雜邏輯下的對象傳遞
10.2.1.4 實現(xiàn)原理
10.2.1.4.1 set方法: public void set(T value){ Thread currentThread = Thread.currentThread(); Values values = values(currentThread); if(values == null) values = initializeValues(currentThread); values.put(this, value); }
10.2.2 MessageQueue
10.2.2.1 插入和讀取,數(shù)據(jù)結(jié)構(gòu)為單鏈表
10.2.2.2 讀取操作中的next實質(zhì)上是無限循環(huán)
10.2.3 Looper
10.2.3.1 退出:quit、quitSately quit——直接退出Looper; quitSafely——把消息隊列中的已有消息處理完畢后才安全退出
10.2.3.2 在子線程中,如果手動為其創(chuàng)建了Looper,那么在所有事情完成后應(yīng)該調(diào)用quit方法來終止Looper,否則這個子線程就會一直處于等待狀態(tài)
10.2.4 Handler工作原理
10.3 主線程的消息循環(huán)
10.3.1 Android的主線程就是ActivityThread
11 11. Android線程和線程池
11.1 概述
11.1.1 AsyncTask底部用到了線程池和Handler
11.1.2 IntentService和HandlerThread則是直接使用了線程
11.1.3 IntentService內(nèi)部采用HandlerThread來執(zhí)行任務(wù),當(dāng)任務(wù)執(zhí)行完畢后IntentService會自動退出;IntentService作用很想一個后臺線程,但是IntentService是一種服務(wù),它不容易被系統(tǒng)殺死從而可以盡量保證任務(wù)的執(zhí)行,直接使用后臺線程的話,則很容易被系統(tǒng)殺死;
11.1.4 HandlerThread是一種具有消息循環(huán)的線程
11.2 主線程和子線程
11.2.1 主:進(jìn)程所擁有的線程
11.2.2 子:執(zhí)行耗時任務(wù)
11.3 線程形態(tài)
11.3.1 AsyncTask
11.3.1.1 封裝了Thread和Handler,但不適合特別耗時的任務(wù)
11.3.1.2 泛型參數(shù):Params、Progress、Result
11.3.1.3 核心方法
11.3.1.3.1 onPreExecute()
11.3.1.3.2 doInBackground(Params... params)
11.3.1.3.3 onProgressUpdate(Progress...values)
11.3.1.3.4 onPostExecute(Result result)
11.3.1.4 限制
11.3.1.4.1 必須在主線程中加載
11.3.1.4.2 對象必須在主線程中創(chuàng)建
11.3.1.4.3 execute必行在UI線程調(diào)用
11.3.1.4.4 不直接調(diào)用核心方法
11.3.1.4.5 兵行、串行的來回改版
11.3.1.5 工作原理
11.3.1.5.1 串行線程池
11.3.1.5.2 Handler切換線程,要求Handler來自主線程
11.3.2 HandlerThread
11.3.2.1 run中通過Looper.prepare()來創(chuàng)建消息隊列,并通過Looper.loop()來開啟消息循環(huán)
11.3.2.2 由于其run方法是一個無限循環(huán),因此當(dāng)明確不需要再使用HandlerThread時可以通過quit或者quitSafely來終止線程執(zhí)行
11.3.3 IntentService
11.3.3.1 抽象類,必須建立它的子類才能使用
11.3.3.2 可以執(zhí)行后臺耗時任務(wù),執(zhí)行完成后自動停止
11.4 線程池
11.4.1 ThreadPoolExecutor
11.4.1.1 參數(shù)
11.4.1.1.1 corePoolSize
11.4.1.1.2 maximumPoolSize
11.4.1.1.3 keepAliveTime
11.4.1.1.4 unit
11.4.1.1.5 workQueue
11.4.1.1.6 threadFactory
11.4.1.1.7 RejectedExecutionHandler handler
11.4.2 分類
11.4.2.1 FixedThreadPool
11.4.2.2 CachedThreadPool
11.4.2.3 ScheduledThreadPool
11.4.2.4 SingleThreadExecutor
12 12. Bitmap的加載和Cache
12.1 高效加載
12.1.1 使用BitmapFactory.Options來加載所需尺寸的圖片
12.1.1.1 使用inSampleSize設(shè)置采樣率
12.1.1.2 如何獲取采樣率
12.1.1.2.1 1. 將inJustDecodeBounds 參數(shù)設(shè)為true并加載圖片
12.1.1.2.2 2. 取出圖片原始寬高信息,對應(yīng)于outWidth和outHeight
12.1.1.2.3 3. 根據(jù)采樣率規(guī)則并結(jié)合目標(biāo)View所需大小計算出采樣率inSampleSize
12.1.1.2.4 4. 將inJustDecodeBounds參數(shù)設(shè)為false,然后重新加載圖片
12.2 緩存策略
12.2.1 常用LRU算法:Least Recently Used
12.2.1.1 LruCache實現(xiàn)內(nèi)存緩存,DiskLruCache充當(dāng)存儲設(shè)備緩存
12.2.2 LruCache
12.2.2.1 使用support-v4包中的LruCache兼容性更好
12.2.2.2 是線程安全的
12.2.2.3 引用的幾種類別
12.2.2.3.1 強(qiáng)引用
12.2.2.3.2 軟引用
12.2.2.3.2.1 內(nèi)存不足時會被gc
12.2.2.3.3 弱引用
12.2.3 DiskLruCache
12.2.3.1 創(chuàng)建
12.2.3.2 添加
12.2.3.3 查找
12.2.4 ImageLoader的實現(xiàn)
13 13. 綜合技術(shù)
13.1 使用CrashHandler來獲取應(yīng)用信息
13.1.1 UncaughtExceptionHandler處理crash——記錄、上報、用戶提醒
13.1.2 使用方法
13.1.2.1 在Application初始化時為線程設(shè)置CrashHandler
13.2 multiDex解決方法數(shù)越界
13.2.1 1. 在build.gradle中添加multidex配置
13.2.2 2. 在代碼中支持multidex功能
13.2.2.1 一、 在manifest中指定Application 為MultiDexApplication
13.2.2.2 二、 讓應(yīng)用繼承自MultiDexApplication
13.2.2.3 三、 重寫 application中的attachBaseContext方法(因為這個方法在onCreate之前執(zhí)行)
13.2.3 3. 指定主dex文件所要包含的類——可以通過-- main-dex-list指定
13.2.3.1 在build.gradle文件中添加afterEvaluate區(qū)域(見書P460)
13.3 動態(tài)加載技術(shù)
13.4 反編譯
14 14. JNI和NDK
15 15. Android性能優(yōu)化
15.1 性能優(yōu)化方法
15.1.1 布局優(yōu)化
15.1.1.1 include標(biāo)簽
15.1.1.2 merge標(biāo)簽
15.1.1.3 ViewStub
15.1.1.3.1 使用時才加載
15.1.1.3.2 暫時不支持merge
15.1.2 繪制優(yōu)化
15.1.2.1 onDraw要避免執(zhí)行大量操作
15.1.3 內(nèi)存泄露優(yōu)化
15.1.3.1 靜態(tài)變量導(dǎo)致
15.1.3.2 單例導(dǎo)致
15.1.3.3 屬性動畫導(dǎo)致
15.1.4 響應(yīng)速度優(yōu)化和ANR日志分析
15.1.4.1 進(jìn)程ANR會在/data/anr目錄下創(chuàng)建traces.txt記錄
15.1.5 ListView和Bitmap優(yōu)化
15.1.5.1 避免getView中耗時
15.1.5.2 根據(jù)滑動狀態(tài)來控制任務(wù)執(zhí)行頻率
15.1.5.3 BitmapFactory.Options進(jìn)行采樣
15.1.6 線程優(yōu)化
15.1.6.1 線程池
15.1.7 建議
15.1.7.1 避免過多對象
15.1.7.2 不要過多使用enum
15.1.7.3 const使用static final修飾
15.1.7.4 使用Android特有的數(shù)據(jù)結(jié)構(gòu),如SparseArray和Pair,它們都具有更好的性能
15.1.7.5 適當(dāng)使用軟引用和弱引用
15.1.7.6 采用內(nèi)存緩存和磁盤緩存
15.1.7.7 盡量采用靜態(tài)內(nèi)部類,可以避免潛在的由于內(nèi)部類而導(dǎo)致的內(nèi)存泄露

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內(nèi)容