1. 程式人生 > >Android開發藝術探索讀書筆記(一)

Android開發藝術探索讀書筆記(一)

           首先向各位嚴重推薦主席這本書《Android開發藝術探索》。

再感謝主席邀請寫這篇讀書筆記 + 書評。書已經完整的翻完一遍了,但是還沒有細緻的品讀並run程式碼,最近有時間正好系統的把整本書從內容到程式碼都梳理一遍,一方面方便自己總結,一方面也為主席宣傳,如果你還在猶豫要不要入手這本書的時候,希望看完我的筆記,能激發你購買的動力。OK,言歸正傳,下面先簡單寫幾句書評,本人技術有限,只是從自身角度出發做一些分享,大神請輕噴。

在你已經厭倦只會做功能+xml堆介面,在你想要了解Android更多的技術細節,在你渴望自己在Android開發上獲得一次涅槃的時候,主席的這本書應運而生了。通讀完本書,第一感覺這本書沒有華麗的辭藻,沒有酷炫的賣弄,沒有生澀的技術詞彙堆砌,有的,只是玉剛童鞋對於技術的執著和熱愛,對於分享的熱忱和真摯。可以說,這就是一本技術人員的書,因為我們熱愛的只是技術而已。全書結構清晰,脈絡整齊,我個人認為分為以下幾個大類:Activity機制,View機制,iPC機制,必須知道的Android核心技術,必須知道的Android優化技術。可以說,這本書是在你熟悉使用api之後進階的第一選擇,因為優秀的程式設計師絕對不是api的搬運工,我們更需要了解優秀的api背後的設計理念和底層機制,只有知道這些,我們才能真正做到融匯貫通,舉一反三,從用api成長到寫api。

這個blog我準備分四到五篇來寫,主要還是記錄閱讀過程中遇到的重難點和tips,也可以看作是提綱挈領,查漏補缺吧。我希望看主席的書如果會有一些模模糊糊的地方,我這幾篇tips能幫助到你,以上。

今天第一篇主要是前兩章+remoteView,加remoteView的原因主要是這貨本質也就是個aidl實現的IPC,就放在一起了,大家發現任何問題也可以在評論中給出,感謝。

Android開發藝術探索Tips

Chapter-1 Activity的生命週期和啟動模式

----------------------------

1. 新Activity是透明主題時,舊Activity不會走onStop;

2. Activity切換時,舊Activity的onPause會先執行,然後才會啟動新的Activity;

3. Activity在異常情況下被回收時,onSaveInstanceState方法會被回撥,回撥時機是在onStop之前,當Activity被重新建立的時 候,onRestoreInstanceState方法會被回撥,時序在onStart之後;

4. Activity的LaunchMode

a. standard 系統預設。每次啟動會重新建立新的例項,誰啟動了這個Activity,這個Activity就在誰的棧裡。

b. singleTop 棧頂複用模式。該Activity的onNewIntent方法會被回撥,onCreate和onStart並不會被呼叫。

c. singleTask 棧內複用模式。只要該Activity在一個棧中存在,都不會重新建立,onNewIntent會被回撥。如果不存在,系統會先尋找是否存在需要的棧,如果不存在該棧,就建立一個任務棧,然後把這個Activity放進去;如果存在,就會建立到已經存在的這個棧中。

d. singleInstance。具有此種模式的Activity只能單獨存在於一個任務棧。

5. 標識Activity任務棧名稱的屬性:TaskAffinity,預設為應用包名。

6. IntentFilter匹配規則。

a. action匹配規則:要求intent中的action 存在 且 必須和過濾規則中的其中一個相同 區分大小寫;

b. category匹配規則:系統會預設加上一個android.intent.category.DEAFAULT,所以intent中可以不存在category,但如果存在就必須匹配其中一個;

c. data匹配規則:data由兩部分組成,mimeType和URI,要求和action相似。如果沒有指定URI,URI但預設值為content和file(schema)

Chapter-2 IPC機制

---------------

1. 使用android:process會帶來的問題:

靜態成員和單例模式完全失效;

SharedPreferences可靠性下降;

Application會多次建立;

2. Binder的工作機制:(Page55)

3. Android中的IPC方式

a. Bundle

b. 檔案共享(不建議使用系統的SharedPreferences)

c. Messenger(輕量級IPC,底層依然是AIDL)工作原理(Page70 & 程式碼)

d. AIDL  

aa. AIDL支援的資料型別:基本資料型別;String和CharSequence;List只支援ArrayList,裡面每個元素都必須被AIDL支援;Map只支援HashMap,裡面每個元素都必須被AIDL支援(包括key和value);Parcelable;AIDL介面本身;  

bb. 服務端可以使用CopyOnWriteArrayList和ConcurrentHashMap來進行自動執行緒同步,客戶端拿到的依然是ArrayList和HashMap;  

cc. 服務端和客戶端之間做監聽器,服務端需要使用RemoteCallbackList,否則客戶端的監聽器無法收到通知(因為服務端實質還是一份新的序列化後的監聽器例項,並不是客戶端那份);  

dd. 客戶端呼叫遠端服務方法時,因為遠端方法執行在服務端的binder執行緒池中,同時客戶端執行緒會被掛起,所以如果該方法過於耗時,而客戶端又是UI執行緒,會導致ANR,所以當確認該遠端方法是耗時操作時,應避免客戶端在UI執行緒中呼叫該方法。同理,當伺服器呼叫客戶端的listener方法時,該方法也執行在客戶端的binder執行緒池中,所以如果該方法也是耗時操作,請確認執行在服務端的非UI執行緒中。另外,因為客戶端的回撥listener執行在binder執行緒池中,所以更新UI需要用到handler。  

ee. 客戶端通過IBinder.DeathRecipient來監聽Binder死亡,也可以在onServiceDisconnected中監聽並重連服務端。區別在於前者是在binder執行緒池中,訪問UI需要用Handler,後者則是UI執行緒。  

ff. 可通過自定義許可權在onBind或者onTransact中進行許可權驗證。

e. ContentProvider(有的手機上會出現不加uses-permission依然可以訪問BookProvider的問題,已和主席確認) f. Socket 一般用於網路通訊,AIDL用這種方式會過於繁瑣,不建議。  

4. Binder連線池,通過BinderPool的方式將Binder的控制與Service本身解耦,同時只需要維護一份Service即可。這裡用到了CountDownLatch,大概解釋下用意:執行緒在await後等待,直到CountDownLatch的計數為0,BinderPool裡使用它的目的是為了保證Activity獲取BinderPool的時候Service已確定bind完成~

Chapter-5 RemoteViews

---------------------

1. Notification。Notification的自定義View只能使用setTextViewText, setImageViewResource, setOnClickPendingIntent等固定方法來設定View,不能像操作普通View的方式來操作。

2. AppWidgetProvider

a.本質是一個廣播,配置步驟:定義介面xml,定義配置資訊xml,定義實現類(繼承AppWidgetProvider),AndroidManifest中宣告。

b.重要回調:onEnable,第一次被新增時呼叫,只有一次;onUpdate,新增或更新時回撥;onDelete,每次刪除時回撥;onDisable,最後一次刪除時回撥;onReceive,接收廣播的action。

3. PendingIntent

a. 典型的使用場景就是和RemoteViews的點選事件配合使用;

b. 支援三種待定Intent:Activity,Service和Broadcast

c. PendingIntent相同的定義:內部的Intent和requestCode都相同。Intent相同的定義:兩個Intent的componentName和intent-filter相同(不包括extras)

d. flag定義:FLAG_NO_CREATE,基本不使用;FLAG_ONE_SHOT,以第一個為準,後續的會全部和第一條保持一致,任意一條被觸發,其他的都cancel;FLAG_CANCEL_CURRENT,前面的相同的PendingIntent都會被cancel,只有最新的可用;FLAG_UDPATE_CURRENT,前面的PendingIntent都會被更新(它們Intent中的extras都會被更新)

4. RemoteViews的內部機制

a. 支援的View型別:Layout:FrameLayout, LinearLayout, RelativeLayout, GridLayout; View: AnalogClock, Button, Chronometer, ImageButton, ImageView, ProgressBar, TextView, ViewFlipper, ListView, GridView, StackView, AdapterViewFlipper, ViewStub。

b. 簡單歸納,客戶端的remoteViews通過action物件,由binder機制來更新服務端的remoteViews,所以RemoteViews本身也實現了Parcelable介面(參考圖Page233)

c. RemoteViews中真正操作View的方法apply和reapply,前者會載入佈局並更新介面,後者則只更新介面。

5. 跨程序的RemoteViews傳遞,模擬通知欄的實現。注意不同應用間RemoteViews的id不同,需要約定名稱然後重新通過Resource.getIdentifier來獲取。