Activity
Service
Broadcast
ContentProvider
Fragment
View
View繪制
View事件分發(fā)
自定義View
View滑動
控件
RecyclerView
ListView
ViewPager
動畫
Bitmap && Drawable
Android線程與進程
Handler/Looper
Binder
序列化
進程鄙笈撸活
AsyncTask
HandlerThread
IntentService
IPC
線程池
Android優(yōu)化
ANR
1. ANR是什么?如何避免和解決ANR?
ANR:Application Not Responding黍匾,即應用無響應。一般有以下三種:
- KeyDispatchTimeout:5s
- BroadcatTimeout:10s
- ServiceTimeout:20s
造成Timeout的原因一般有兩種:
主線程阻塞在了某個消息中
當前事件正在被處理但是沒有被處理完
操作阻塞的原因可能是:
- 耗時的網絡操作
- 大量的數據讀寫
- 數據庫操作
- 硬件操作
- 線程等待
- 發(fā)生了死鎖
- 動畫耗時
- Cpu負載高
問題定位:
- ANR產生時费尽,系統(tǒng)會生成一個tarces.txt的文本文件放在/data/anr下至会,最新的ANR信息在最開始的位置。通過ADB命令
adb pull data/anr/traces.txt .
可以導出到本地分析矮慕。 - 使用Android Studio中的Profile工具可以方便的得到每個方法的運行時間
- 使用Android SDK中提供的Debug類:
- 在開始的記錄的點寫上代碼Debug.startMethodTracing("TAG");
- 在終止記錄的點寫上代碼Debug.stopMethodTracing();
- 通過adb pull /data/tracePath.trace導出文件并使用Android Studio打開分析
解決方法:
- 不要在主線程中去做耗時操作帮匾,將耗時操作放在子線程中去。通過Thread痴鳄、HandlerThread瘟斜、IntentService、AsyncTask
- 同樣由于Service/Broadcast運行在主線程夏跷,Service中也不能做耗時操作
- 在使用Thread或者HandlerThread時哼转,可以嘗試調用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設置較低優(yōu)先級,否則依然會降低程序響應槽华,因為默認Thread的優(yōu)先級和主線程相同壹蔓。
- 任何UI線程中的方法都應該簡短快捷,類似調整Bitmap大小這種需要長時間計算的操作猫态,都應該執(zhí)行在工作線程中佣蓉。
- BroadcastReceiver中的onReceive()方法如果必須執(zhí)行耗時操作披摄,建議在這個方法中開啟IntentService來執(zhí)行耗時操作。
內存泄漏memory leak
1. 內存泄漏的原因勇凭、場景疚膊、解決方法?
根本原因:長生命周期的對象持有短生命周期的對象虾标,導致短生命周期對象就無法及時釋放寓盗。
泄漏場景:
非靜態(tài)內部類的靜態(tài)實例
非靜態(tài)內部類會持有外部類的引用,如果這個非靜態(tài)內部類的實例恰好是個靜態(tài)實例璧函,那么這個實例就會長時間的存在傀蚌,從而導致外部類長時間被引用,就無法被回收蘸吓,從而造成外部類的內存泄漏善炫。匿名內部類
匿名內部類同樣會持有外部類的引用,如果這個匿名內部類中做了耗時操作库继,就會導致外部類長時間被引用從而無法回收箩艺。-
Handler內存泄漏
Handler內存泄漏也可以歸納為非靜態(tài)內部類導致的,Handler發(fā)送的消息Message首先會將自己的target指向當前Handler對象宪萄,然后這個Message會被加入到Looper中的MessageQueue中等待被處理艺谆。如果消息長時間得不到處理,Handler就會被一直引用拜英,從而外部類也就一直被引用擂涛,導致內存泄漏。這種情況下建議:
- 使用靜態(tài)Handler
- 在退出時移除消息隊列中的消息
- 外部類引用使用弱引用處理
Context內存泄漏
根據場景確定使用Activity的Context還是ApplicationContext聊记,因為兩者生命周期不同撒妈,對于不必須使用Activity的Context的場景(Dialog),一律采用ApplicationContext排监。單例模式是最常見的發(fā)生此泄漏的場景狰右。比如傳入一個Activity的Context被靜態(tài)類引用,導致無法回收舆床。-
靜態(tài)View內存泄漏
使用靜態(tài)View可以避免每次啟動Activity都去讀取并渲染View棋蚌,但是View會持有Activity的引用,導致無法回收挨队。解決辦法時在Activity銷毀的時候將靜態(tài)View設置為null(View一旦被加載到界面上會持有一個Context對象的引用谷暮,這里就是Activity。)
WebView導致的內存泄漏
WebView只要使用一次盛垦,內存就不會被釋放湿弦,所以WebView都存在內存泄漏的問題。通常的解決辦法時為WebView單獨打開一個進程腾夯,使用AIDL進行通信颊埃,根據業(yè)務需求在合適的時機釋放掉蔬充。資源對象未關閉
集合中的對象未清理
-
Bitmap內存泄漏
避免靜態(tài)變量持有大的Bitmap對象。
監(jiān)聽器未關閉
很多需要register和unregister的系統(tǒng)服務要在合適的時候進行unregister班利,手動添加的listener也要及時移除饥漫。
檢測方法:
- LeakCanary
OOM (out of memory)
冷啟動&&熱啟動
性能優(yōu)化
UI優(yōu)化
其它
Context
1. 談談你對Android中Context的理解?
Context:包含上下文信息的一個參數罗标。Android 中的 Context 分三種:
Application Context
Activity Context
Service Context
它描述的是一個應用程序環(huán)境的信息庸队, 通過它我們可以獲取應用程序的資源和類,也包括一些應用級別操作闯割, 例如: 啟動一個 Activity皿哨, 發(fā)送廣播, 接受 Intent 信息等纽谒。
Application
權限
Android中的強、弱如输、軟鼓黔、虛應用
LruCache && DiskLruCache
第三方庫
OkHttp
Glide
1. 說說View的繪制流程
- Measure過程:View的繪制其實就是一個深度遍歷的過程。這里有一個MeasureSpec的概念不见,每一個View都有一個MeasureSpec澳化,它由父View根據自己的MeasureSpec和子View的LayoutParam共同決定。MeasureSpec有三個取值:
- MeasureSpec. UNSPECIFIED:不限制View大小
- MeasureSpec.EXACTLY:
- MeasureSpec.AT_MOST:
- Layout過程:
- Draw過程:
- Draw the background
- If necessary, save the canvas' layers to prepare for fading
- Draw view's content
- Draw children
- If necessary, draw the fading edges and restore layers
- Draw decorations (scrollbars for instance)
2. 說說Activity的啟動模式
啟動模式涉及到一個Task的概念稳吮,Task說的是為了完成一個任務的一系列的Activity的集合缎谷,這些Activity可以是來自不同的應用的。比如一個應用需要寫一封郵件灶似,它用Intent去打開了郵件這個應用的寫郵件的MailActivity列林,這個Activity就可以和其它Activity同屬一個Task。
啟動模式有四種:
- standard:
- singleTask:
- singleTop:
- singleInstance:
標記位有三個:
- FLAG_ACTIVITY_NEW_TASK:
- FLAG_ACTIVITY_SINGLE_TOP:
- FLAG_ACTIVITY_CLEAR_TOP:
標記位優(yōu)先級>啟動模式
3. 說說Activity的生命周期
- onCreate-->onStart()-->onResume()-->onPause()-->onStop()-->onDestrory()
-->onRestart() - 正常關閉情況下onSaveInstanceState() 以及 onRestoreInstanceState()這兩個方法是不會被調用的酪惭。它們只會在Activity不正常關閉下調用希痴。我們說的視圖恢復就是指的不正常關閉時候,Activity再次打開的時候要讓用戶感覺到Activity并沒有被關閉春感。
- 建議onStop()中保存數據
4. 說說View事件分發(fā)
手指在屏幕的動作被抽象成了MotionEvent對象砌创,根據不同情境分成了MotionEvent.ACTION_DOWN、MotionEvent.ACTION_POINTER_DOWN鲫懒、MotionEvent.ACTION_MOVE嫩实、MotionEvent.ACTION_UP、MotionEvent.ACTON_CANCLE窥岩。事件分發(fā)主要就是當ACTION_DOWN以及ACTION_POINTER_DOWN兩個事件到來時尋找新的TouchTarget的過程甲献。主要有三個大的方法參與這個過程:
- dispatchTouchEvent()
- onInterceptTouchEvent() (ViewGroup獨有)
- onTouchEvent()
其中dispatchTouchEvent負責尋找到一個新的TouchTarget,,并把事件交給TouchTarget颂翼。onInterceptTouchEvent()指示當前ViewGroup是否攔截此次事件竟纳。onTouchEvent()處理事件撵溃,它的返回代表當前事件是否被這個View消耗。
onTouch()--> onTouchEvent()-->onClick()