經(jīng)典試題

資料來源:http://www.reibang.com/p/916b2f8e1456

Activity

Activity的生命周期抽米?

onCreate() 表示Activity正在被創(chuàng)建做初始化工作虽界,如setContentView界面資源忍抽、初始化數(shù)據(jù)。Bundle參數(shù)為該Activity上次被異常情況銷毀時(shí)保存的狀態(tài)信息。
onStart() 表示Activity正在啟動(dòng),這時(shí)Activity可見但不在前臺(tái)。無法與用戶交互担租。
onResume() 表示Activity獲取焦點(diǎn),可見且在前臺(tái)活動(dòng)抵怎》芫龋可以與用戶交互岭参。
onPause() 表示Activity正在停止,可做數(shù)據(jù)存儲(chǔ)尝艘,停止動(dòng)畫等操作演侯。
onStop() 表示Activity即將停止,可做取消網(wǎng)絡(luò)連接背亥、注銷廣播接收器等秒际。
onDestroy() 表示Activity即將銷毀,可做釋放資源等操作狡汉。
onRestart() 表示Activity重新啟動(dòng)娄徊,由不可見到可見時(shí)會(huì)調(diào)用,

onStart()和onResume()/onPause()和onStop()的區(qū)別盾戴?

onStart()與onStop()是從Activity是否可見這個(gè)角度調(diào)用
onResume()和onPause()是從Activity是否顯示在前臺(tái)這個(gè)角度來回調(diào)

Activity A啟動(dòng)另一個(gè)Activity B會(huì)回調(diào)哪些方法寄锐?如果Activity B是完全透明呢?如果啟動(dòng)的是一個(gè)Dialog呢尖啡?

會(huì)調(diào)用A 的onPause() -> B 的onCreate() -> onStart() -> onResume() -> A的onStop()
不會(huì)調(diào)用A 的onStop()方法橄仆,Dialog同理。

談?wù)刼nSaveInstanceState()方法衅斩?何時(shí)會(huì)調(diào)用盆顾?

當(dāng)非人為終止Activity時(shí)會(huì)調(diào)用onSavaInstanceState()來保存狀態(tài)。(系統(tǒng)配置發(fā)生改變時(shí)導(dǎo)致Activity被殺死并重新創(chuàng)建矛渴、資源內(nèi)存不足導(dǎo)致低優(yōu)先級(jí)的Activity被殺死)
該方法在onStop()方法之前調(diào)用,與onPause()沒有時(shí)序關(guān)系惫搏。

onSaveInstanceState()與onPause()的區(qū)別具温?

onSaveInstanceState()適用于非人為終止Activity時(shí)臨時(shí)性狀態(tài)的保存。
onPause() 適用于對(duì)數(shù)據(jù)的持久化保存筐赔,停止動(dòng)畫等铣猩。

說下Activity的四種啟動(dòng)模式?

standard標(biāo)準(zhǔn)模式茴丰、默認(rèn)模式:每次啟動(dòng)一個(gè)Activity都會(huì)創(chuàng)建一個(gè)新的實(shí)例达皿,并放入棧頂位置。
singleTop棧頂復(fù)用模式:如果啟動(dòng)的Activity已經(jīng)位于任務(wù)棧的棧頂贿肩,就不會(huì)重新創(chuàng)建實(shí)例峦椰,而是調(diào)用onNewIntent(intent)方法。反之創(chuàng)建新的實(shí)例加入棧中汰规。
singleTask棧內(nèi)復(fù)用模式:只要該Activity在一個(gè)任務(wù)棧中存在汤功,就不會(huì)重新創(chuàng)建新的實(shí)例。并把棧中在其之上的其他Activity Destroy掉溜哮,調(diào)用onNewIntent(intent)方法滔金。如果不存在色解,創(chuàng)建新的實(shí)例并入棧。
singleInstance單實(shí)例模式:Activity只能單獨(dú)位于一個(gè)任務(wù)棧中餐茵,并且這個(gè)任務(wù)棧只存在這一個(gè)實(shí)例科阎。

談?wù)剆ingleTop和singleTask的區(qū)別以及應(yīng)用場景

singleTop允許同個(gè)Activity在棧中可以有多個(gè)實(shí)例,即可以重復(fù)創(chuàng)建忿族;為防止快速點(diǎn)擊時(shí)多次startActivity锣笨,可以將目標(biāo)Activity設(shè)置為singleTop。
singleTask同個(gè)Activity在棧中只有一個(gè)實(shí)例肠阱,即不存在重復(fù)創(chuàng)建票唆;常用于主頁和登陸頁

了解哪些Activity啟動(dòng)模式的標(biāo)記位?

Intent.FLAG_ACTIVITY_NEW_TASK:使用一個(gè)新的Task來啟動(dòng)Activity
Intent.FLAG_ACTIVITY_SINGLE_TOP:類似singleTop
Intent.FLAG_ACTIVITY_CLEAR_TOP:類似singleTask
Intent.FLAG_ACTIVITY_NO_HISTORY:使用這種模式啟動(dòng)Activity屹徘,當(dāng)該Activity啟動(dòng)其他Activity后走趋,該Activity就消失了,不會(huì)保留在Task棧中噪伊。

onNewIntent()調(diào)用時(shí)機(jī)簿煌?

啟動(dòng)模式為singleTop或singleTask的Activity會(huì)出現(xiàn)回調(diào)onNewIntent()的情況

如何避免配置改變時(shí)Activity重建?

在AndroidManifest.xml中對(duì)應(yīng)的Activity中設(shè)置android:configChanges="orientation|keyboardHidden|screenSize"鉴吹。此時(shí)發(fā)生屏幕旋轉(zhuǎn)姨伟,該Activity不會(huì)被系統(tǒng)殺死和重建,會(huì)調(diào)用onConfigurationChanged方法豆励。

優(yōu)先級(jí)低的Activity在內(nèi)存不足被回收后怎樣做可以恢復(fù)到銷毀前狀態(tài)夺荒?

低優(yōu)先級(jí)的Activity在內(nèi)存不足被回收后重新啟動(dòng)會(huì)引發(fā)Activity重建,會(huì)調(diào)用onRestoreInstanceState方法良蒸,并將onSaveInstanceState方法保存的Bunble對(duì)象作為參數(shù)傳到onRestoreInstanceState 和 onCreate方法中技扼。因此可通過onRestoreInstanceState(Bundle savedInstanceState)和onCreate((Bundle savedInstanceState)來判斷Activity是否被重建,并取出數(shù)據(jù)進(jìn)行恢復(fù)嫩痰。在onCreate中需要判斷savedInstanceState是否為空剿吻。

如何啟動(dòng)其他應(yīng)用的Activity?

在保證有權(quán)限訪問的情況下串纺,通過隱式Intent進(jìn)行目標(biāo)Activity的IntentFilter匹配

Activity的啟動(dòng)過程丽旅?

調(diào)用startActivity()后經(jīng)過重重方法會(huì)轉(zhuǎn)移到ActivityManagerService的startActivity(),并通過一個(gè)IPC回到ActivityThread的內(nèi)部類ApplicationThread中纺棺,并調(diào)用其scheduleLaunchActivity()將啟動(dòng)Activity的消息發(fā)送并交由Handler H處理榄笙。Handler H對(duì)消息的處理會(huì)調(diào)用handleLaunchActivity()->performLaunchActivity()得以完成Activity對(duì)象的創(chuàng)建和啟動(dòng)。

Fragment

談一談Fragment的生命周期祷蝌?

Fragment生命周期方法:onAttach() -> onCreate() -> onCreateView() -> onActivityCreated() -> onStart() -> onResume() -> onPause() -> onStop() -> onDestroyView() -> onDestroy() -> onDetach()
onAttach() 當(dāng)Fragment和Activity建立關(guān)聯(lián)時(shí)調(diào)用
onCreateView() 當(dāng)Fragment創(chuàng)建視圖時(shí)調(diào)用
onActivityCreated() 當(dāng)與Fragment相關(guān)聯(lián)的Activity完成onCreate()之后調(diào)用
onDestroyView() 在Fragment中的布局被移除時(shí)調(diào)用
onDetach() 當(dāng)Fragment和Activity解除關(guān)聯(lián)時(shí)調(diào)用

Activity和Fragment的異同办斑?

相同點(diǎn):它們都可包含布局、可有自己的生命周期,F(xiàn)ragment可看似迷你活動(dòng)乡翅。
不同點(diǎn):Fragment是依附在Activity上的鳞疲,多了些和宿主Activity相關(guān)的生命周期方法,如onAttach()蠕蚜、onCreateView()尚洽、onActivityCreated()、onDestroyView()靶累、onDetach()腺毫;另外,F(xiàn)ragment的生命周期方法是由宿主Activity而不是操作系統(tǒng)調(diào)用的挣柬。

Activity和Fragment的關(guān)系潮酒?

它可作為Activity界面的組成部分,可在Activity運(yùn)行中實(shí)現(xiàn)動(dòng)態(tài)地加入邪蛔、移除和交換急黎。
一個(gè)Activity中可同時(shí)出現(xiàn)多個(gè)Fragment,一個(gè)Fragment也可在多個(gè)Activity中使用侧到。
Activity的FragmentManager負(fù)責(zé)調(diào)用隊(duì)列中Fragment的生命周期方法勃教,只要Fragment的狀態(tài)與Activity的狀態(tài)保持了同步,宿主Activity的FragmentManager便會(huì)繼續(xù)調(diào)用其他生命周期方法以繼續(xù)保持Fragment與Activity的狀態(tài)一致匠抗。

何時(shí)會(huì)考慮使用Fragment故源?

用兩個(gè)Fragment封裝兩個(gè)界面模塊,這樣只使一套代碼就能適配兩種設(shè)備汞贸,達(dá)到兩種界面效果
單一場景切換時(shí)使用Fragment更輕量化绳军,如ViewPager和Fragment搭配使用

Service

談一談Service的生命周期?

onCreate():服務(wù)第一次被創(chuàng)建時(shí)調(diào)用
onStartCommand():服務(wù)啟動(dòng)時(shí)調(diào)用
onBind():服務(wù)被綁定時(shí)調(diào)用
onUnBind():服務(wù)被解綁時(shí)調(diào)用
onDestroy():服務(wù)停止時(shí)調(diào)用

Service的兩種啟動(dòng)方式矢腻?區(qū)別在哪门驾?

第一種:startService()方法可以啟動(dòng)一個(gè)Service,并回調(diào)服務(wù)中的onStartCommand()方法踏堡。如果該服務(wù)之前還沒創(chuàng)建猎唁,那么回調(diào)的順序是onCreate() -> onStartCommand()咒劲;如果服務(wù)是開啟狀態(tài)顷蟆,在次調(diào)用startService()不會(huì)回調(diào)onCreate()方法。服務(wù)啟動(dòng)了之后會(huì)一直保持運(yùn)行狀腐魂,直到 stopService() 或 stopSelf() 方法被調(diào)用帐偎,服務(wù)停止并回調(diào)onDestroy()(無論調(diào)用多少次startService()方法,只需調(diào)用一次stopService()或stopSelf()方法蛔屹,服務(wù)就會(huì)停止了)削樊。
第二種:bindService()方法可以綁定一個(gè)Service,并回調(diào)服務(wù)中的onBind()方法。如果該服務(wù)之前還沒創(chuàng)建漫贞,那么回調(diào)的順序是onCreate() -> onBind()甸箱;如果服務(wù)是開啟狀態(tài),在次調(diào)用startService()不會(huì)回調(diào)onCreate()方法迅脐。調(diào)用方可以獲取到onBind()方法里返回的IBinder對(duì)象的實(shí)例芍殖,從而實(shí)現(xiàn)和服務(wù)進(jìn)行通信。只要調(diào)用方和服務(wù)之間的連接沒有斷開谴蔑,服務(wù)就會(huì)一直保持運(yùn)行狀態(tài)豌骏,直到調(diào)用了 unbindService()方法服務(wù)會(huì)停止,回調(diào)順序onUnBind() -> onDestroy()隐锭。

一個(gè)Activty先start一個(gè)Service后窃躲,再bind時(shí)會(huì)回調(diào)什么方法?此時(shí)如何做才能回調(diào)Service的onDestroy()方法钦睡?

這兩種啟動(dòng)方法并不沖突蒂窒,startService()啟動(dòng)Service之后赎婚,再bindService()綁定,此時(shí)只會(huì)回調(diào)onBind()方法
需要同時(shí)調(diào)用 stopService()和 unbindService()方法才能讓服務(wù)銷毀掉挣输。

Service如何和Activity進(jìn)行通信纬凤?

通過bindService()可以實(shí)現(xiàn)Activity調(diào)用Service中的方法。
通過廣播實(shí)現(xiàn)Service向Activity發(fā)送消息撩嚼。

用過哪些系統(tǒng)Service停士?

WINDOW_SERVICE 管理打開的窗口程序
LAYOUT_INFLATER_SERVICE 取得XML里定義的View
ACTIVITY_SERVICE 管理應(yīng)用程序的系統(tǒng)狀態(tài)
POWER_SERVICE 電源服務(wù)
ALARM_SERVICE 鬧鐘服務(wù)
NOTIFICATION_SERVICE 狀態(tài)欄服務(wù)
KEYAUARD_SERVICE 鍵盤鎖服務(wù)

是否能在Service進(jìn)行耗時(shí)操作?如果非要可以怎么做完丽?

Service默認(rèn)并不會(huì)運(yùn)行在子線程中恋技,也不運(yùn)行在一個(gè)獨(dú)立的進(jìn)程中,它同樣執(zhí)行在主線程中(UI線程)逻族。
手動(dòng)打開一個(gè)子線程蜻底,否則有可能出現(xiàn)主線程被阻塞(ANR)的情況。

前臺(tái)服務(wù)是什么聘鳞?和普通服務(wù)的不同薄辅?如何去開啟一個(gè)前臺(tái)服務(wù)?

前臺(tái)服務(wù)的服務(wù)狀態(tài)可以被用戶看到抠璃。它和普通服務(wù)最大的區(qū)別是站楚,前者會(huì)一直有一個(gè)正在運(yùn)行的圖標(biāo)在系統(tǒng)的狀態(tài)欄顯示,下拉狀態(tài)欄后可以看到更加詳細(xì)的信息搏嗡,且當(dāng)系統(tǒng)內(nèi)存不足服務(wù)被殺死時(shí)窿春,通知會(huì)被移除拉一。
創(chuàng)建一個(gè)Notification實(shí)例旧乞,調(diào)用startForeground()方法尺栖,不需要NotificationManager將通知顯示出來货徙。

是否了解ActivityManagerService痴颊,談?wù)勊l(fā)揮什么作用蠢棱?

ActivityManagerService是Android中最核心的服務(wù) 泻仙, 主要負(fù)責(zé)系統(tǒng)中四大組件的啟動(dòng)玉转、切換、調(diào)度及應(yīng)用進(jìn)程的管理和調(diào)度等工作刺下。

如何保證Service不被殺死橘茉?

在Service的onStartCommand()中設(shè)置flages值為START_STICKY畅卓,使得Service被殺死后嘗試再次啟動(dòng)Service
提升Service優(yōu)先級(jí)惕鼓,比如設(shè)置為一個(gè)前臺(tái)服務(wù)
在Activity的onDestroy()通過發(fā)送廣播,并在廣播接收器的onReceive()中啟動(dòng)Service一膨。

BroadcastReceiver

廣播有幾種形式豹绪?什么特點(diǎn)?

普通廣播:一種完全異步執(zhí)行的廣播巷蚪,在廣播發(fā)出之后屁柏,所有的廣播接收器幾乎都會(huì)在同一時(shí)刻接收到這條廣播消息淌喻,因此它們接收的先后是隨機(jī)的。
有序廣播:一種同步執(zhí)行的廣播烁落,在廣播發(fā)出之后伤塌,同一時(shí)刻只會(huì)有一個(gè)廣播接收器能夠收到這條廣播消息每聪,當(dāng)這個(gè)廣播接收器中的邏輯執(zhí)行完畢后,廣播才會(huì)繼續(xù)傳遞童本,所以此時(shí)的廣播接收器是有先后順序的绑蔫,且優(yōu)先級(jí)(priority)高的廣播接收器會(huì)先收到廣播消息配深。有序廣播可以被接收器截?cái)嗍沟煤竺娴慕邮掌鳠o法收到它。
本地廣播:發(fā)出的廣播只能夠在應(yīng)用程序的內(nèi)部進(jìn)行傳遞缸托,并且廣播接收器也只能接收本應(yīng)用程序發(fā)出的廣播嗦董。
粘性廣播:這種廣播會(huì)一直滯留,當(dāng)有匹配該廣播的接收器被注冊后匹摇,該接收器就會(huì)收到此條廣播廊勃。

廣播的兩種注冊形式坡垫?區(qū)別在哪?

靜態(tài)注冊:廣播接收器即便程序未啟動(dòng)也能接收到廣播溉卓。
動(dòng)態(tài)注冊:廣播接收器必須要在程序啟動(dòng)之后才能接收到廣播桑寨。當(dāng)用來注冊廣播的Activity關(guān)掉后尉尾,廣播也就失效了

ContentProvider & 數(shù)據(jù)存儲(chǔ)

ContentProvider了解多少辨图?

ContentProvider可以讓不同應(yīng)用程序之間進(jìn)行數(shù)據(jù)共享,它還可以選擇只對(duì)哪一部分?jǐn)?shù)據(jù)進(jìn)行共享,從而保證程序中的隱私數(shù)據(jù)不會(huì)有泄漏風(fēng)險(xiǎn)瞻讽。

Android中提供哪些數(shù)據(jù)持久存儲(chǔ)的方法速勇?

File 文件存儲(chǔ):Context類中提供了openFileInput()和openFileOutput()方法來打開數(shù)據(jù)文件里的文件IO流。
SharedPreferences存儲(chǔ):一種輕型的數(shù)據(jù)存儲(chǔ)方式都伪,常用來存儲(chǔ)一些簡單的配置信息陨晶,基于XML文件存儲(chǔ)key-value鍵值對(duì)數(shù)據(jù)。
SQLite數(shù)據(jù)庫存儲(chǔ):一款輕量級(jí)的關(guān)系型數(shù)據(jù)庫褐耳,它的運(yùn)算速度非呈。快,占用資源很少注盈,在存儲(chǔ)大量復(fù)雜的關(guān)系型數(shù)據(jù)的時(shí)可以使用老客。
ContentProvider:四大組件之一鳍鸵,用于數(shù)據(jù)的存儲(chǔ)和共享偿乖,不僅可以讓不同應(yīng)用程序之間進(jìn)行數(shù)據(jù)共享贪薪,還可以選擇只對(duì)哪一部分?jǐn)?shù)據(jù)進(jìn)行共享,可保證程序中的隱私數(shù)據(jù)不會(huì)有泄漏風(fēng)險(xiǎn)霍弹。

Java中的I/O流讀寫怎么做?

Context類中提供了openFileInput()和openFileOutput()方法來打開數(shù)據(jù)文件里的文件IO流钝计。
bufferedReader.readLine()讀
bufferedWriter.write(text)寫

SharePreferences適用情形?使用中需要注意什么本鸣?

SharePreferences是一種輕型的數(shù)據(jù)存儲(chǔ)方式荣德,適用于存儲(chǔ)一些簡單的配置信息,如int署咽、string窒升、boolean、float和long蓉媳。由于系統(tǒng)對(duì)SharedPreferences的讀/寫有一定的緩存策略殴瘦,即在內(nèi)存中有一份該文件的緩存蚪腋,因此在多進(jìn)程模式下立帖,其讀/寫會(huì)變得不可靠,甚至丟失數(shù)據(jù)绑咱。

了解SQLite中的事務(wù)處理嗎?是如何做的窿克?

SQLite在做CRDU操作時(shí)都默認(rèn)開啟了事務(wù),然后把SQL語句翻譯成對(duì)應(yīng)的SQLiteStatement并調(diào)用其相應(yīng)的CRUD方法谋右,此時(shí)整個(gè)操作還是在rollback journal這個(gè)臨時(shí)文件上進(jìn)行啸蜜,只有操作順利完成才會(huì)更新.db數(shù)據(jù)庫,否則會(huì)被回滾辈挂。

使用SQLite做批量操作有什么好的方法嗎衬横?

使用SQLiteDatabase的beginTransaction()方法開啟一個(gè)事務(wù),將批量操作SQL語句轉(zhuǎn)化成SQLiteStatement并進(jìn)行批量操作终蒂,結(jié)束后endTransaction()

如果現(xiàn)在要?jiǎng)h除SQLite中表的一個(gè)字段如何做蜂林?

SQLite數(shù)據(jù)庫只允許增加表字段而不允許修改和刪除表字段,只能采取復(fù)制表思想噪叙,即創(chuàng)建一個(gè)新表保留原表想要的字段子眶、再將原表刪除渴杆。

使用SQLite時(shí)會(huì)有哪些優(yōu)化操作点寥?

使用事務(wù)做批量操作。
及時(shí)關(guān)閉Cursor,避免內(nèi)存泄漏
耗時(shí)操作異步化:數(shù)據(jù)庫的操作屬于本地IO,通常比較耗時(shí)隅津,建議將這些耗時(shí)操作放入異步線程中處理
ContentValues的容量調(diào)整:ContentValues內(nèi)部采用HashMap來存儲(chǔ)Key-Value數(shù)據(jù),ContentValues初始容量為8线定,擴(kuò)容時(shí)翻倍芭商。因此建議對(duì)ContentValues填入的內(nèi)容進(jìn)行估量鉴竭,設(shè)置合理的初始化容量,減少不必要的內(nèi)部擴(kuò)容操作
使用索引加快檢索速度:對(duì)于查詢操作量級(jí)較大、業(yè)務(wù)對(duì)查詢要求較高的推薦使用索引

View

MotionEvent是什么?包含幾種事件猾普?什么條件下會(huì)產(chǎn)生?

ACTION_DOWN:第一個(gè)手指觸摸屏幕
ACTION_MOVE:手指在屏幕上移動(dòng)
ACTION_UP:最后一個(gè)手指離開屏幕
ACTION_CANCEL:手勢被取消赏参,不再接受后續(xù)事件紊浩;從當(dāng)前控件轉(zhuǎn)移到外層控件時(shí)會(huì)觸發(fā)
ACTION_OUTSIDE:標(biāo)志著用戶觸碰到了正常的UI邊界
ACTION_POINTER_DOWN:出現(xiàn)一個(gè)新的觸摸點(diǎn)
ACTION_POINTER_UP:非最后一個(gè)手指抬起

scrollTo()和scrollBy()的區(qū)別?

scrollBy內(nèi)部調(diào)用了scrollTo,它是基于當(dāng)前位置的相對(duì)滑動(dòng);而scrollTo是絕對(duì)滑動(dòng)
兩者都只能對(duì)view內(nèi)容進(jìn)行滑動(dòng)岛都,而不能使view本身滑動(dòng)荣赶。

Scroller中最重要的兩個(gè)方法是什么剩燥?主要目的是?

在MotionEvent.ACTION_UP事件觸發(fā)時(shí)調(diào)用startScroll()方法葛躏,該方法并沒有進(jìn)行實(shí)際的滑動(dòng)操作芬骄,而是記錄滑動(dòng)相關(guān)量
馬上調(diào)用invalidate/postInvalidate()方法,請求View重繪赌莺,導(dǎo)致View.draw方法被執(zhí)行
緊接著會(huì)調(diào)用View.computeScroll()方法骇吭,此方法是空實(shí)現(xiàn)霜大,需要自己處理邏輯遮婶。具體邏輯是:先判斷computeScrollOffset()袱衷,若為true(表示滾動(dòng)未結(jié)束)垦垂,則執(zhí)行scrollTo()方法差购,它會(huì)再次調(diào)用postInvalidate(),如此反復(fù)執(zhí)行汉嗽,直到返回值為false欲逃。

談一談View的事件分發(fā)機(jī)制?

事件傳遞順序:Activity(Window) -> ViewGroup -> View
dispatchTouchEvent:進(jìn)行事件的分發(fā)(傳遞)饼暑。返回值是 boolean 類型稳析,受當(dāng)前onTouchEvent和下級(jí)view的dispatchTouchEvent影響
onInterceptTouchEvent:對(duì)事件進(jìn)行攔截洗做。該方法只在ViewGroup中有,View(不包含 ViewGroup)是沒有的彰居。一旦攔截诚纸,則執(zhí)行ViewGroup的onTouchEvent,在ViewGroup中處理事件陈惰,而不接著分發(fā)給View畦徘。且只調(diào)用一次,所以后面的事件都會(huì)交給ViewGroup處理抬闯。
onTouchEvent:進(jìn)行事件處理井辆。

如何解決View的滑動(dòng)沖突?

外部攔截法:指點(diǎn)擊事件都先經(jīng)過父容器的攔截處理溶握,如果父容器需要此事件就攔截杯缺,否則就不攔截。onInterceptTouchEvent方法
內(nèi)部攔截法:指父容器不攔截任何事件睡榆,而將所有的事件都傳遞給子容器萍肆,如果子容器需要此事件就直接消耗,否則就交由父容器進(jìn)行處理胀屿。子View的dispatchTouchEvent方法并設(shè)置requestDisallowInterceptTouchEvent方法匾鸥,父View需要重寫onInterceptTouchEvent方法

談一談View的工作原理?

View工作流程簡單來說就是碉纳,先measure測量勿负,用于確定View的測量寬高,再 layout布局劳曹,用于確定View的最終寬高和四個(gè)頂點(diǎn)的位置奴愉,最后 draw繪制,用于將View 繪制到屏幕上

MeasureSpec是什么铁孵?有什么作用锭硼?

UNSPECIFIED:父容器不對(duì)View有任何限制,要多大有多大蜕劝。常用于系統(tǒng)內(nèi)部檀头。
EXACTLY(精確模式):父視圖為子視圖指定一個(gè)確切的尺寸SpecSize。對(duì)應(yīng)LyaoutParams中的match_parent或具體數(shù)值岖沛。
AT_MOST(最大模式):父容器為子視圖指定一個(gè)最大尺寸SpecSize暑始,View的大小不能大于這個(gè)值。對(duì)應(yīng)LayoutParams中的wrap_content婴削。
作用:通過寬測量值widthMeasureSpec和高測量值heightMeasureSpec決定View的大小

自定義View/ViewGroup需要注意什么廊镜?

設(shè)置View支持wrap_content
設(shè)置View支持padding
盡量不要在View中使用Handler
View中有線程或動(dòng)畫需要及時(shí)停止
處理滑動(dòng)嵌套

onTouch()、onTouchEvent()和onClick()關(guān)系唉俗?

優(yōu)先度onTouch()>onTouchEvent()>onClick()嗤朴。因此onTouchListener的onTouch()方法會(huì)先觸發(fā)配椭;如果onTouch()返回false才會(huì)接著觸發(fā)onTouchEvent(),同樣的雹姊,內(nèi)置諸如onClick()事件的實(shí)現(xiàn)等等都基于onTouchEvent()股缸;如果onTouch()返回true,這些事件將不會(huì)被觸發(fā)吱雏。

SurfaceView和View的區(qū)別敦姻?

View需要在UI線程對(duì)畫面進(jìn)行刷新,而SurfaceView可在子線程進(jìn)行頁面的刷新
View適用于主動(dòng)更新的情況坎背,而SurfaceView適用于被動(dòng)更新替劈,如頻繁刷新,這是因?yàn)槿绻褂肰iew頻繁刷新會(huì)阻塞主線程得滤,導(dǎo)致界面卡頓
SurfaceView在底層已實(shí)現(xiàn)雙緩沖機(jī)制陨献,而View沒有臀叙,因此SurfaceView更適用于需要頻繁刷新慕趴、刷新時(shí)數(shù)據(jù)處理量很大的頁面

invalidate()和postInvalidate()的區(qū)別?

invalidate()與postInvalidate()都用于刷新View画株,主要區(qū)別是invalidate()在主線程中調(diào)用沮协,若在子線程中使用需要配合handler龄捡;而postInvalidate()可在子線程中直接調(diào)用。

Animation

Android中有哪幾種類型的動(dòng)畫慷暂?

ViewAnimation補(bǔ)間動(dòng)畫:容易設(shè)置和能滿足許多應(yīng)用程序的需要聘殖。AlphaAnimation(透明度動(dòng)畫)、RotateAnimation(旋轉(zhuǎn)動(dòng)畫)行瑞、ScaleAnimation(縮放動(dòng)畫)奸腺、TranslateAnimation(平移動(dòng)畫)四種類型的補(bǔ)間動(dòng)畫。并且View動(dòng)畫框架還提供了動(dòng)畫集合類(AnimationSet)血久,通過動(dòng)畫集合類可以將多個(gè)補(bǔ)間動(dòng)畫以組合的形式顯示出來突照,不能真正的改變view的位置。
PropertyAnimation屬性動(dòng)畫:這種動(dòng)畫可以設(shè)置給任何Object氧吐,包括那些還沒有渲染到屏幕上的對(duì)象讹蘑。這種動(dòng)畫是可擴(kuò)展的,可以讓你自定義任何類型和屬性的動(dòng)畫筑舅。對(duì)該類對(duì)象進(jìn)行動(dòng)畫操作座慰,真正改變了對(duì)象的屬性。
DrawableAnimation:專門用來一個(gè)一個(gè)的顯示Drawable的resources豁翎,就像放幻燈片一樣角骤。

幀動(dòng)畫在使用時(shí)需要注意什么?

使用禎動(dòng)畫要注意不能使用尺寸過大的圖片心剥,否則容易造成OOM

View動(dòng)畫和屬性動(dòng)畫的區(qū)別邦尊?

View動(dòng)畫:通過不斷圖形變換實(shí)現(xiàn)動(dòng)畫效果,不能真正的改變view的位置优烧;只能作用在View上蝉揍。
屬性動(dòng)畫:通過動(dòng)態(tài)改變對(duì)象的屬性實(shí)現(xiàn)動(dòng)畫效果,真正改變View的位置畦娄;能作用在任何對(duì)象上又沾。

View動(dòng)畫為何不能真正改變View的位置?而屬性動(dòng)畫為何可以熙卡?

View動(dòng)畫改變的只是View的顯示杖刷,而沒有改變View的響應(yīng)區(qū)域;而屬性動(dòng)畫會(huì)通過反射技術(shù)來獲取和執(zhí)行屬性的get驳癌、set方法滑燃,從而改變了對(duì)象位置的屬性值。

屬性動(dòng)畫插值器和估值器的作用颓鲜?

插值器(Interpolator):根據(jù)時(shí)間流逝的百分比計(jì)算出當(dāng)前屬性值改變的百分比表窘。確定了動(dòng)畫效果變化的模式,如勻速變化甜滨、加速變化等等乐严。
類型估值器(TypeEvaluator):根據(jù)當(dāng)前屬性改變的百分比計(jì)算出改變后的屬性值。針對(duì)于屬性動(dòng)畫衣摩,View動(dòng)畫不需要類型估值器昂验。

Drawable

了解哪些Drawable?適用場景艾扮?

BitmapDrawable 表示一張圖片
NinePatchDrawable 可自動(dòng)地根據(jù)所需的寬/高對(duì)圖片進(jìn)行相應(yīng)的縮放并保證不失真(表示一張.9格式的圖片)
ShapeDrawable 表示純色既琴、有漸變效果的基礎(chǔ)幾何圖形(矩形,圓形栏渺,線條等)
LayerDrawable 可通過將不同的Drawable放置在不同的層上面從而達(dá)到一種疊加后的效果
StateListDrawable 表示一個(gè)Drawable的集合且每個(gè)Drawable對(duì)應(yīng)著View的一種狀態(tài)
TransitionDrawable LayerDrawable的子類呛梆,實(shí)現(xiàn)兩層 Drawable之間的淡入淡出效果。
InsetDrawable 表示把一個(gè)Drawable嵌入到另外一個(gè)Drawable的內(nèi)部磕诊,并在四周留一些間距填物。
ScaleDrawable 表示將Drawable縮放到一定比例。
ClipDrawable 表示裁剪一個(gè)Drawable霎终。

mipmap系列中xxxhdpi滞磺、xxhdpi、xhdpi莱褒、hdpi击困、mdpi和ldpi存在怎樣的關(guān)系?

表示不同密度的圖片資源,像素從高到低依次排序?yàn)閤xxhdpi>xxhdpi>xhdpi>hdpi>mdpi>ldpi阅茶,根據(jù)手機(jī)的dpi不同加載不同密度的圖片

dp蛛枚、dpi、px的區(qū)別脸哀?

px:像素蹦浦,如分辨率1920x1080表示高為1920個(gè)像素、寬為1080個(gè)像素
dpi:每英寸的像素點(diǎn)
dp:密度無關(guān)像素撞蜂,是個(gè)相對(duì)值

res目錄和assets目錄的區(qū)別盲镶?

res/raw中的文件會(huì)被映射到R.java文件中,訪問時(shí)可直接使用資源ID蝌诡,不可以有目錄結(jié)構(gòu)
assets文件夾下的文件不會(huì)被映射到R.java中溉贿,訪問時(shí)需要AssetManager類,可以創(chuàng)建子文件夾

Window

Activity浦旱、View宇色、Window三者之間的關(guān)系?

在Activity啟動(dòng)過程其中的attach()方法中初始化了PhoneWindow闽寡,而PhoneWindow是Window的唯一實(shí)現(xiàn)類代兵,然后Activity通過setContentView將View設(shè)置到了PhoneWindow上,而View通過WindowManager的addView()爷狈、removeView()植影、updateViewLayout()對(duì)View進(jìn)行管理。

Window的內(nèi)部機(jī)制

ViewManager接口中定義三個(gè)對(duì)Window操作方法:添加涎永、更新和刪除思币。
WindowManager也是一個(gè)接口,它繼承了ViewManager接口
WindowManager的具體實(shí)現(xiàn)類是WindowManagerImpl羡微,并沒有直接實(shí)現(xiàn)Window的三大操作谷饿,而是交給了WindowManagerGlobal。
WindowManagerGlobal以單例模式向外提供自己的實(shí)例妈倔,因此通過WindowManagerGlobal的addView()博投、updateViewLayout()、removeView()實(shí)現(xiàn)WindowManager對(duì)Window的添加盯蝴、刪除和修改毅哗。
Windows的三大操作最終都會(huì)通過一個(gè)IPC過程移交給WindowManagerService。
Window和View通過ViewRootImpl來聯(lián)系捧挺,ViewRootImpl可控制View的測量虑绵、布局和重繪。

Window有哪幾種類型闽烙?

應(yīng)用Window:對(duì)應(yīng)一個(gè)Activity翅睛。
子Window:不能單獨(dú)存在,需附屬特定的父Window。如Dialog捕发。
系統(tǒng)Window: 需申明權(quán)限才能創(chuàng)建疏旨。如Toast。

Activity創(chuàng)建和Dialog創(chuàng)建過程的異同爬骤?

相同點(diǎn)
創(chuàng)建WindowDialog充石。和Activity類似莫换,同樣是通過PolicyManager.makeNewWindow()來實(shí)現(xiàn)霞玄。
初始化DecorView并將Dialog的視圖添加到DecorView中去。和Activity類似拉岁,同樣是通過Window.setContentView() 來實(shí)現(xiàn)坷剧。
將DecorView添加到Window中顯示。和Activity一樣喊暖,都是在自身要出現(xiàn)在前臺(tái)時(shí)才會(huì)將添加Window惫企。
不同點(diǎn)
Dialog.show()方法:完成DecorView的顯示。
WindowManager.remoteViewImmediate()方法:當(dāng)Dialog被dismiss時(shí)移除DecorView陵叽。

Hander

談?wù)勏C(jī)制Hander狞尔?作用?有哪些要素巩掺?流程是怎樣的偏序?

作用:跨線程通信。
使用場景:當(dāng)子線程中進(jìn)行耗時(shí)操作后需要更新UI時(shí)胖替,通過Handler將有關(guān)UI的操作切換到主線程中執(zhí)行研儒。
Message:需要被傳遞的消息,其中包含了消息ID独令,消息處理對(duì)象以及處理的數(shù)據(jù)等端朵,由MessageQueue統(tǒng)一列隊(duì),最終由Handler處理燃箭。
MessageQueue:用來存放Handler發(fā)送過來的消息冲呢,內(nèi)部通過單鏈表的數(shù)據(jù)結(jié)構(gòu)來維護(hù)消息列表,等待Looper的抽取招狸。
Handler:負(fù)責(zé)發(fā)送及處理Message消息敬拓。
Looper:通過Looper.loop()不斷地從MessageQueue中抽取Message,按分發(fā)機(jī)制將消息分發(fā)給目標(biāo)處理者瓢颅。
Handler.sendMessage()發(fā)送消息時(shí)恩尾,會(huì)通過MessageQueue.enqueueMessage()向MessageQueue中添加一條消息;通過Looper.loop()開啟循環(huán)后挽懦,不斷輪詢調(diào)用MessageQueue.next()翰意;調(diào)用目標(biāo)Handler.dispatchMessage()去傳遞消息,目標(biāo)Handler收到消息后調(diào)用Handler.handlerMessage()處理消息。

為什么系統(tǒng)不建議在子線程訪問UI冀偶?

UI控件非線程安全醒第,在多線程中并發(fā)訪問可能會(huì)導(dǎo)致UI控件處于不可預(yù)期的狀態(tài)。而不對(duì)UI控件的訪問加上鎖機(jī)制的原因有:上鎖會(huì)讓UI控件變得復(fù)雜和低效进鸠;上鎖后會(huì)阻塞某些進(jìn)程的執(zhí)行

一個(gè)Thread可以有幾個(gè)Looper稠曼?幾個(gè)Handler?

一個(gè)Thread只能有一個(gè)Looper客年,可以有多個(gè)Handler霞幅;
Looper有一個(gè)MessageQueue,可以處理來自多個(gè)Handler的Message量瓜;
MessageQueue有一組待處理的Message司恳,這些Message可來自不同的Handler;
Message中記錄了負(fù)責(zé)發(fā)送和處理消息的Handler绍傲;
Handler中有Looper和MessageQueue扔傅;

如何將一個(gè)Thread線程變成Looper線程?Looper線程有哪些特點(diǎn)烫饼?

通過Looper.prepare()可將一個(gè)Thread線程轉(zhuǎn)換成Looper線程猎塞。Looper線程和普通Thread不同,它通過MessageQueue來存放消息和事件杠纵、Looper.loop()進(jìn)行消息輪詢荠耽。

可以在子線程直接new一個(gè)Handler嗎?那該怎么做淡诗?

不同于主線程直接new一個(gè)Handler骇塘,由于子線程的Looper需要手動(dòng)去創(chuàng)建,在創(chuàng)建Handler時(shí)需要多一些方法: Looper.prepare();Looper.loop();

Message可以如何創(chuàng)建韩容?哪種效果更好款违,為什么?

Message msg = new Message();
Message msg = Message.obtain();
Message msg = handler.obtainMessage();
后兩種方法都是從整個(gè)Messge池中返回一個(gè)新的Message實(shí)例群凶,能有效避免重復(fù)Message創(chuàng)建對(duì)象插爹,因此更鼓勵(lì)這種方式創(chuàng)建###Message

這里的ThreadLocal有什么作用?

ThreadLocal類可實(shí)現(xiàn)線程本地存儲(chǔ)的功能请梢,把共享數(shù)據(jù)的可見范圍限制在同一個(gè)線程之內(nèi)赠尾,無須同步就能保證線程之間不出現(xiàn)數(shù)據(jù)爭用的問題,這里可理解為ThreadLocal幫助Handler找到本線程的Looper毅弧。

主線程中Looper的輪詢死循環(huán)為何沒有阻塞主線程气嫁?

Android是依靠事件驅(qū)動(dòng)的,通過Loop.loop()不斷進(jìn)行消息循環(huán)够坐,可以說Activity的生命周期都是運(yùn)行在 Looper.loop()的控制之下寸宵,一旦退出消息循環(huán)崖面,應(yīng)用也就退出了。而所謂的導(dǎo)致ANR多是因?yàn)槟硞€(gè)事件在主線程中處理時(shí)間太耗時(shí)梯影,因此只能說是對(duì)某個(gè)消息的處理阻塞了Looper.loop()巫员。

使用Hanlder的postDealy()后消息隊(duì)列會(huì)發(fā)生什么變化?

post delay的Message并不是先等待一定時(shí)間再放入到MessageQueue中甲棍,而是直接進(jìn)入并阻塞當(dāng)前線程简识,然后將其delay的時(shí)間和隊(duì)頭的進(jìn)行比較,按照觸發(fā)時(shí)間進(jìn)行排序感猛,如果觸發(fā)時(shí)間更近則放入隊(duì)頭七扰,保證隊(duì)頭的時(shí)間最小、隊(duì)尾的時(shí)間最大唱遭。此時(shí)戳寸,如果隊(duì)頭的Message正是被delay的,則將當(dāng)前線程堵塞一段時(shí)間拷泽,直到等待足夠時(shí)間再喚醒執(zhí)行該Message,否則喚醒后直接執(zhí)行袖瞻。

線程

Android中還了解哪些方便線程切換的類司致?

AsyncTask:一種輕量級(jí)的異步任務(wù)類。底層封裝了線程池和Handler聋迎,便于執(zhí)行后臺(tái)任務(wù)以及在子線程中進(jìn)行UI操作脂矫。
HandlerThread:一種具有消息循環(huán)的線程,其內(nèi)部可使用Handler霉晕。
IntentService:是一種異步庭再、會(huì)自動(dòng)停止的服務(wù),內(nèi)部采用HandlerThread牺堰。

AsyncTask相比Handler有什么優(yōu)點(diǎn)拄轻?不足呢?
Handler的缺點(diǎn):代碼相對(duì)臃腫伟葫;多任務(wù)同時(shí)執(zhí)行時(shí)不易精確控制線程恨搓。
AsyncTask的優(yōu)點(diǎn):創(chuàng)建異步任務(wù)更簡單,直接繼承AsyncTask便可實(shí)現(xiàn)后臺(tái)異步任務(wù)的執(zhí)行和進(jìn)度的回調(diào)更新UI筏养,而無需編寫任務(wù)線程和Handler實(shí)例就能完成相同的任務(wù)斧抱。

使用AsyncTask需要注意什么?

不要直接調(diào)用onPreExecute()渐溶、doInBackground()辉浦、onProgressUpdate()、onPostExecute()和onCancelled()方法
開始和結(jié)束異步任務(wù)的方法必須在主線程調(diào)用茎辐,一個(gè)異步對(duì)象只能調(diào)用一次execute()方法宪郊,

AsyncTask中的五個(gè)核心方法

onPreExecute():運(yùn)行在主線程眉睹,在異步任務(wù)執(zhí)行之前被調(diào)用》媳欤可用于進(jìn)行一些界面上的初始化操作竹海。
doInBackground():運(yùn)行在子線程,用于處理所有耗時(shí)任務(wù)丐黄,更新UI需調(diào)用 publishProgress()方法斋配。任務(wù)一旦完成就通過return語句將任務(wù)的執(zhí)行結(jié)果返回。
onProgressUpdate():運(yùn)行在主線程灌闺,在后臺(tái)任務(wù)中調(diào)用publishProgress()之后該方法會(huì)被調(diào)用艰争,可利用方法中攜帶的參數(shù)如Progress來對(duì)UI進(jìn)行相應(yīng)地更新。
onPostExecute():運(yùn)行在主線程桂对,在異步任務(wù)執(zhí)行完畢并通過return語句返回時(shí)被調(diào)用甩卓,可利用方法中返回的數(shù)據(jù)來進(jìn)行一些UI操作。
onCancelled():運(yùn)行在主線程蕉斜,當(dāng)異步任務(wù)被取消時(shí)調(diào)用逾柿,用于界面取消的更新。

AsyncTask中使用的線程池大姓恕机错?

SerialExecutor:用于任務(wù)的排隊(duì),默認(rèn)是串行的線程池父腕,在3.0以前核心線程數(shù)為5弱匪、線程池大小為128,而3.0以后變?yōu)橥粫r(shí)間只能處理一個(gè)任務(wù)
THREAD_POOL_EXECUTOR:用于真正執(zhí)行任務(wù)璧亮。

HandlerThread有什么特點(diǎn)萧诫?

HandlerThread是一個(gè)線程類,它繼承自Thread枝嘶。與普通Thread不同帘饶,HandlerThread具有消息循環(huán)的效果,這是因?yàn)樗鼉?nèi)部HandlerThread.run()方法中有Looper躬络,能通過Looper.prepare()來創(chuàng)建消息隊(duì)列尖奔,并通過Looper.loop()來開啟消息循環(huán)。

快速實(shí)現(xiàn)子線程使用Handler

實(shí)例化一個(gè)HandlerThread對(duì)象穷当,參數(shù)是該線程名稱提茁;通過handlerThread.start()啟動(dòng)線程;實(shí)例化一個(gè)Handler并傳入handlerThread中l(wèi)ooper對(duì)象馁菜,使得與HandlerThread綁定茴扁;利用handler即可執(zhí)行異步任務(wù);當(dāng)不需要HandlerThread時(shí)汪疮,通過quit()或quitSafely()方法來終止線程的執(zhí)行峭火。

IntentService的工作原理毁习?

在IntentService.onCreate()方法中實(shí)例化一個(gè)HandlerThread,利用其內(nèi)部的Looper會(huì)實(shí)例化一個(gè)ServiceHandler對(duì)象卖丸;
任務(wù)請求的Intent會(huì)被封裝到Message并通過ServiceHandler發(fā)送給Looper的MessageQueue纺且,最終在HandlerThread中執(zhí)行;
在ServiceHandler.handleMessage()中會(huì)調(diào)用IntentService.onHandleIntent()和stopSelf()稍浆,可在onHandleIntent方法中處理后臺(tái)任務(wù)的邏輯载碌,stopSelf方法終止服務(wù)。

IntentService的特點(diǎn)衅枫?

相比于線程:由于是服務(wù)嫁艇,優(yōu)先級(jí)比線程高,更不容易被系統(tǒng)殺死弦撩。因此較適合執(zhí)行一些高優(yōu)先級(jí)的后臺(tái)任務(wù)步咪。
相比于普通Service:可自動(dòng)創(chuàng)建子線程來執(zhí)行任務(wù),且任務(wù)執(zhí)行完畢后自動(dòng)退出益楼。

為何不用bindService方式創(chuàng)建IntentService猾漫?

當(dāng)有Intent任務(wù)請求時(shí)會(huì)把Intent封裝到Message,然后ServiceHandler會(huì)把消息發(fā)送出偏形,而發(fā)送消息是在onStartCommand()完成的静袖,只能通過startService()才可走該生命周期方法,因此不能通過bindService創(chuàng)建IntentService俊扭。

線程池的好處、原理坠陈、類型萨惑?

線程池的優(yōu)點(diǎn):

重用線程池中的線程,避免線程的創(chuàng)建和銷毀帶來的性能消耗仇矾;
有效控制線程池的最大并發(fā)數(shù)庸蔼,避免大量的線程之間因互相搶占系統(tǒng)資源而導(dǎo)致阻塞現(xiàn)象;
進(jìn)行線程管理贮匕,提供定時(shí)/循環(huán)間隔執(zhí)行等功能

線程池的原理

通過ThreadPoolExecutor并通過一系列參數(shù)來配置各種各樣的線程池姐仅,具體參數(shù):

corePoolSize核心線程數(shù):一般會(huì)在線程中一直存活
maximumPoolSize最大線程數(shù):當(dāng)活動(dòng)線程數(shù)達(dá)到這個(gè)數(shù)值后,后續(xù)的任務(wù)將會(huì)被阻塞
keepAliveTime非核心線程超時(shí)時(shí)間:超過這個(gè)時(shí)長刻盐,閑置的非核心線程就會(huì)被回收
unit:用于指定keepAliveTime參數(shù)的時(shí)間單位
workQueue任務(wù)隊(duì)列:通過線程池的execute()方法提交的Runnable對(duì)象會(huì)存儲(chǔ)在這個(gè)參數(shù)中掏膏。
threadFactory:線程工廠,可創(chuàng)建新線程
handler:在線程池?zé)o法執(zhí)行新任務(wù)時(shí)進(jìn)行調(diào)度

線程池的類型

FixThreadPool:線程數(shù)量固定的線程池敦锌,所有線程都是核心線程馒疹,當(dāng)線程空閑時(shí)不會(huì)被回收,能快速響應(yīng)外界請求乙墙。
CachedThreadPool:線程數(shù)量不定的線程池颖变,只有非核心線程生均,空閑線程有超時(shí)機(jī)制,超時(shí)回收腥刹,適合于執(zhí)行大量的耗時(shí)較少的任務(wù)
ScheduledThreadPool:核心線程數(shù)量固定马胧,非核心線程數(shù)量不定,適合于執(zhí)行定時(shí)任務(wù)和固定周期的任務(wù)衔峰。
SingleThreadExecutor:只有一個(gè)核心線程佩脊,可確保所有的任務(wù)都在同一個(gè)線程中按順序執(zhí)行,無需處理線程同步問題朽色。

ThreadPoolExecutor的工作策略邻吞?

若程池中的線程數(shù)量未達(dá)到核心線程數(shù),則會(huì)直接啟動(dòng)一個(gè)核心線程執(zhí)行任務(wù)葫男。
若線程池中的線程數(shù)量已達(dá)到或者超過核心線程數(shù)量抱冷,則任務(wù)會(huì)被插入到任務(wù)列表等待執(zhí)行。 若任務(wù)無法插入到任務(wù)列表中梢褐,往往由于任務(wù)列表已滿旺遮,此時(shí)如果線程數(shù)量未達(dá)到線程池最大線程數(shù),則會(huì)啟動(dòng)一個(gè)非核心線程執(zhí)行任務(wù)盈咳;線程數(shù)量已達(dá)到線程池規(guī)定的最大值耿眉,則拒絕執(zhí)行此任務(wù)。

什么是ANR鱼响?什么情況會(huì)出現(xiàn)ANR鸣剪?如何避免?在不看代碼的情況下如何快速定位出現(xiàn)ANR問題所在丈积?

ANR(Application Not Responding筐骇,應(yīng)用無響應(yīng)):當(dāng)操作在一段時(shí)間內(nèi)系統(tǒng)無法處理時(shí),會(huì)在系統(tǒng)層面彈出ANR對(duì)話框江滨。
產(chǎn)生ANR可能是因?yàn)?s內(nèi)無響應(yīng)用戶輸入事件铛纬、10s內(nèi)未結(jié)束BroadcastReceiver、20s內(nèi)未結(jié)束Service
想要避免ANR就不要在主線程做耗時(shí)操作唬滑,而是通過開子線程操作告唆。

IPC(跨進(jìn)程通信)

Android中進(jìn)程和線程的關(guān)系?

進(jìn)程是操作系統(tǒng)分配和管理資源的單位晶密,線程是CPU調(diào)度和管理的單位擒悬,是CPU調(diào)度的最小單元
進(jìn)程擁有獨(dú)立的地址空間,一個(gè)進(jìn)程崩潰后惹挟,在保護(hù)模式下不會(huì)對(duì)其他進(jìn)程產(chǎn)生影響茄螃,而線程間共享地址空間,線程有自己的堆棧和局部變量连锯,一個(gè)線程崩潰會(huì)導(dǎo)致整個(gè)進(jìn)程崩潰掉归苍。
一個(gè)進(jìn)程可包含多個(gè)線程用狱,即一個(gè)應(yīng)用程序上可以同時(shí)執(zhí)行多個(gè)任務(wù)。

為何需要進(jìn)行IPC拼弃?多進(jìn)程通信可能會(huì)出現(xiàn)什么問題夏伊?

所有運(yùn)行在不同進(jìn)程的四大組件,只要它們之間需要通過內(nèi)存共享數(shù)據(jù)吻氧,都會(huì)共享失敗溺忧。由于Android為每個(gè)應(yīng)用分配了獨(dú)立的虛擬機(jī),不同的虛擬機(jī)在內(nèi)存分配上有不同的地址空間
靜態(tài)變量和單例模式失效:由獨(dú)立的虛擬機(jī)造成盯孙。
線程同步機(jī)制失效:由獨(dú)立的虛擬機(jī)造成
SharedPreference的不可靠下降: SharedPreferences不支持兩個(gè)進(jìn)程同時(shí)進(jìn)行讀寫操作鲁森,即不支持并發(fā)讀寫,有一定幾率導(dǎo)致數(shù)據(jù)丟失振惰。
Application多次創(chuàng)建:Android系統(tǒng)會(huì)為新的進(jìn)程分配獨(dú)立虛擬機(jī)歌溉,相當(dāng)于系統(tǒng)又把這個(gè)應(yīng)用重新啟動(dòng)了一次

什么是序列化?Serializable接口和Parcelable接口的區(qū)別骑晶?為何推薦使用后者痛垛?

序列化表示將一個(gè)對(duì)象轉(zhuǎn)換成可存儲(chǔ)或可傳輸?shù)臓顟B(tài)。序列化后的對(duì)象可以在網(wǎng)絡(luò)上進(jìn)行傳輸桶蛔,也可以存儲(chǔ)到本地匙头。
Serializable:Java序列化接口,將一個(gè)對(duì)象轉(zhuǎn)化成可存儲(chǔ)或可傳輸?shù)臓顟B(tài)仔雷,操作簡單蹂析、效率低、開銷大碟婆,ObjectOutputStream和ObjectInputStream過程都需要大量的I/O操作识窿。適合將對(duì)象序列化到存儲(chǔ)設(shè)備或?qū)?duì)象序列化后通過網(wǎng)絡(luò)設(shè)備傳輸。
Parcelable:Android序列化接口脑融,將一個(gè)對(duì)象進(jìn)行分解,且分解后的每一個(gè)部分都是傳遞可支持的類型缩宜。操作比較麻煩肘迎、效率高。主要用在內(nèi)存的序列化锻煌。

Android中為何新增Binder來作為主要的IPC方式妓布?

傳輸效率高、可操作性強(qiáng):傳輸效率主要影響因素是內(nèi)存拷貝的次數(shù)宋梧,拷貝次數(shù)越少匣沼,傳輸速率越高。
實(shí)現(xiàn)C/S架構(gòu)方便:Linux的眾IPC方式除了Socket以外都不是基于C/S架構(gòu)捂龄,而Socket主要用于網(wǎng)絡(luò)間的通信且傳輸效率較低释涛。Binder基于C/S 架構(gòu) 加叁,Server端與Client端相對(duì)獨(dú)立,穩(wěn)定性較好唇撬。
安全性高:傳統(tǒng)Linux IPC的接收方無法獲得對(duì)方進(jìn)程可靠的UID/PID它匕,從而無法鑒別對(duì)方身份;而Binder機(jī)制為每個(gè)進(jìn)程分配了UID/PID且在Binder通信時(shí)會(huì)根據(jù)UID/PID進(jìn)行有效性檢測窖认。

Binder框架中ServiceManager的作用豫柬?

在Binder框架定義了四個(gè)角色:Server,Client扑浸,ServiceManager和Binder驅(qū)動(dòng)烧给。其中Server、Client喝噪、ServiceManager運(yùn)行于用戶空間础嫡,Binder驅(qū)動(dòng)運(yùn)行于內(nèi)核空間。
ServiceManager:服務(wù)的管理者仙逻,將Binder名字轉(zhuǎn)換為Client中對(duì)該Binder的引用驰吓,使得Client可以通過Binder名字獲得Server中Binder實(shí)體的引用。
Server&Client:服務(wù)器&客戶端系奉。在Binder驅(qū)動(dòng)和ServiceManager提供的基礎(chǔ)設(shè)施上檬贰,進(jìn)行Client-Server之間的通信。

Android中有哪些基于Binder的IPC方式缺亮?簡單對(duì)比下翁涤?

Bundle:Bundle實(shí)現(xiàn)了Parcelable接口,方便在不同的進(jìn)程中傳輸數(shù)據(jù)萌踱。支持在activity葵礼、service、receiver之間通過intent.putExtra()傳遞Bundle數(shù)據(jù)并鸵。Bundle內(nèi)部是通過ArrayMap來存取數(shù)據(jù)鸳粉。Bundle不支持的數(shù)據(jù)類型無法在進(jìn)程中被傳遞
Messager:底層實(shí)現(xiàn)是AIDL,即對(duì)AIDL進(jìn)行了封裝园担,更便于進(jìn)行進(jìn)程間通信届谈。支持一對(duì)多串行通信,支持實(shí)時(shí)通信弯汰。
文件共享:兩個(gè)進(jìn)程通過讀/寫同一個(gè)文件來交換數(shù)據(jù)艰山。比如A進(jìn)程把數(shù)據(jù)寫入文件,B進(jìn)程通過讀取這個(gè)文件來獲取數(shù)據(jù)咏闪。對(duì)數(shù)據(jù)同步要求不高的進(jìn)程之間進(jìn)行通信曙搬,并且要妥善處理并發(fā)讀/寫的問題。
ContentProvider:專門用來進(jìn)行不同應(yīng)用間數(shù)據(jù)共享的方式。
AIDL:支持一對(duì)多并發(fā)通信纵装,支持實(shí)時(shí)通信征讲。
Socket:不僅可跨進(jìn)程,還可以跨設(shè)備通信搂擦。網(wǎng)絡(luò)數(shù)據(jù)交換

是否了解AIDL稳诚?原理是什么?如何優(yōu)化多模塊都使用AIDL的情況瀑踢?

如果在一個(gè)進(jìn)程中要調(diào)用另一個(gè)進(jìn)程中對(duì)象的方法扳还,可使用AIDL生成可序列化的參數(shù),AIDL會(huì)生成一個(gè)服務(wù)端對(duì)象的代理類橱夭,通過它客戶端實(shí)現(xiàn)間接調(diào)用服務(wù)端對(duì)象的方法氨距。
當(dāng)有多個(gè)業(yè)務(wù)模塊都需要AIDL來進(jìn)行IPC,此時(shí)需要為每個(gè)模塊創(chuàng)建特定的aidl文件棘劣,那么相應(yīng)的Service就會(huì)很多俏让。必然會(huì)出現(xiàn)系統(tǒng)資源耗費(fèi)嚴(yán)重、應(yīng)用過度重量級(jí)的問題茬暇。解決辦法是建立Binder連接池首昔,即將每個(gè)業(yè)務(wù)模塊的Binder請求統(tǒng)一轉(zhuǎn)發(fā)到一個(gè)遠(yuǎn)程Service中去執(zhí)行,從而避免重復(fù)創(chuàng)建Service糙俗。
每個(gè)業(yè)務(wù)模塊創(chuàng)建自己的AIDL接口并實(shí)現(xiàn)此接口勒奇,然后向服務(wù)端提供自己的唯一標(biāo)識(shí)和其對(duì)應(yīng)的Binder對(duì)象。服務(wù)端只需要一個(gè)Service巧骚,服務(wù)器提供一個(gè)queryBinder接口赊颠,它會(huì)根據(jù)業(yè)務(wù)模塊的特征來返回相應(yīng)的Binder對(duì)像,不同的業(yè)務(wù)模塊拿到所需的Binder對(duì)象后就可進(jìn)行遠(yuǎn)程方法的調(diào)用了

內(nèi)存

加載圖片的時(shí)候需要注意什么劈彪?

直接加載大容量的高清Bitmap很容易出現(xiàn)顯示不完整竣蹦、內(nèi)存溢出OOM的問題,所以最好按一定的采樣率將圖片縮小后再加載進(jìn)來
為減少流量消耗沧奴,可對(duì)圖片采用內(nèi)存緩存策略痘括,又為了避免圖片占用過多內(nèi)存導(dǎo)致內(nèi)存溢出,最好以軟引用方式持有圖片
如果還需要網(wǎng)上下載圖片滔吠,注意要開子線程去做下載的耗時(shí)操作

LRU算法的原理远寸?

LruCache(內(nèi)存緩存):LruCache類是一個(gè)線程安全的泛型類:內(nèi)部采用一個(gè)LinkedHashMap以強(qiáng)引用的方式存儲(chǔ)外界的緩存對(duì)象,并提供get和put方法來完成緩存的獲取和添加操作屠凶,當(dāng)緩存滿時(shí)會(huì)移除較早使用的緩存對(duì)象,再添加新的緩存對(duì)象肆资。
DiskLruCache(磁盤緩存): 通過將緩存對(duì)象寫入文件系統(tǒng)從而實(shí)現(xiàn)緩存效果矗愧。

項(xiàng)目中如何做性能優(yōu)化的?

布局優(yōu)化:布局嵌套過深;使用合適的布局三種常見的ViewGroup的繪制速度:FrameLayout > LinerLayout > RelativeLayout唉韭;使用include標(biāo)簽可以指定插入一段布局文件到當(dāng)前布局夜涕。這樣的話既提高了布局復(fù)用,也減少了我們的代碼書寫属愤,<merge>標(biāo)簽可以和<include>的標(biāo)簽一起使用從而減少布局層級(jí)女器;ViewStub延時(shí)加載;移除Activity默認(rèn)背景住诸,在不需要Activity的默認(rèn)背景減少Activity啟動(dòng)時(shí)的渲染時(shí)間驾胆,提升啟動(dòng)效率。
線程優(yōu)化:使用AsyncTask或者線程池對(duì)線程進(jìn)行管理贱呐,可以提升APP的性能丧诺。推薦使用Rxjava來實(shí)現(xiàn)異步操作,既方便又優(yōu)雅奄薇。
內(nèi)存泄漏優(yōu)化:內(nèi)存泄露會(huì)導(dǎo)致APP占用內(nèi)存過高驳阎,影響效率,嚴(yán)重的話會(huì)導(dǎo)致OOM馁蒂。因此如果項(xiàng)目存在內(nèi)存泄露的話要優(yōu)先解決呵晚。查找內(nèi)存泄露可以用LeakCanary等工具。
繪制優(yōu)化:View過度繪制沫屡;onDraw中不要?jiǎng)?chuàng)建新的局部對(duì)象饵隙;onDraw方法中不要做耗時(shí)的任務(wù),也不能執(zhí)行成千上萬次的循環(huán)操作谁鳍,大量的循環(huán)仍然十分搶占CPU的時(shí)間片癞季,這會(huì)造成View的繪制過程不流暢。
響應(yīng)速度優(yōu)化:避免在主線程中做耗時(shí)操作
列表優(yōu)化:列表控件優(yōu)化convertView的復(fù)用倘潜,ViewHolder的使用避免重復(fù)遍歷節(jié)點(diǎn)
Bitmap優(yōu)化: 對(duì)加載圖片進(jìn)行壓縮绷柒,避免加載圖片多大導(dǎo)致OOM出現(xiàn)

內(nèi)存泄漏和內(nèi)存溢出的區(qū)別

內(nèi)存泄漏(Memory Leak)是指程序在申請內(nèi)存后挎塌,無法釋放已申請的內(nèi)存空間桐臊。是造成應(yīng)用程序OOM的主要原因之一艾岂。
內(nèi)存溢出(out of memory)是指程序在申請內(nèi)存時(shí)蔼啦,沒有足夠的內(nèi)存空間供其使用滔灶。

內(nèi)存泄漏是什么璧微?為什么會(huì)發(fā)生戳吝?常見哪些內(nèi)存泄漏的例子定躏?都是怎么解決的澜掩?

內(nèi)存泄漏(Memory Leak)是指程序在申請內(nèi)存后购披,無法釋放已申請的內(nèi)存空間。
發(fā)生內(nèi)存泄漏是由于長周期對(duì)象持有對(duì)短周期對(duì)象的引用肩榕,使得短周期對(duì)象不能被及時(shí)回收刚陡。
動(dòng)畫:無限循環(huán)動(dòng)畫,導(dǎo)致動(dòng)畫一直播放。
解決方法:當(dāng)播放的Activity退出筐乳,在onDestroy中停止動(dòng)畫
靜態(tài)成員View:靜態(tài)成員生命周期與應(yīng)用的生命周期一樣歌殃,當(dāng)前View持有Activity的引用,當(dāng)前Activity銷毀蝙云,而他的引用一直存在氓皱,導(dǎo)致當(dāng)前Activity無法被回收。
Handler導(dǎo)致的內(nèi)存泄漏:Message持有對(duì)Handler的引用勃刨,而非靜態(tài)內(nèi)部類的Handler又隱式持有對(duì)外部類Activity的引用波材,使得引用關(guān)系會(huì)保持至消息得到處理,從而阻止了Activity的回收朵你。
解決辦法:使用靜態(tài)內(nèi)部類+WeakReference弱引用各聘;當(dāng)外部類結(jié)束生命周期時(shí)清空消息隊(duì)列。
單例模式導(dǎo)致的內(nèi)存泄漏
匿名內(nèi)部類導(dǎo)致的內(nèi)存泄漏:匿名內(nèi)部類隱式持有對(duì)所在Activity的引用抡医。
解決辦法:靜態(tài)內(nèi)部類或獨(dú)立出來躲因;內(nèi)部采用弱引用
資源未關(guān)閉導(dǎo)致的內(nèi)存泄漏:未及時(shí)注銷資源導(dǎo)致內(nèi)存泄漏,如BraodcastReceiver忌傻、File大脉、Cursor、Stream水孩、Bitmap等镰矿。
解決辦法:在Activity銷毀的時(shí)候要及時(shí)關(guān)閉或者注銷。

什么情況會(huì)導(dǎo)致內(nèi)存溢出俘种?

內(nèi)存泄漏是導(dǎo)致內(nèi)存溢出的主要原因秤标;直接加載大圖片也易造成內(nèi)存溢出

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市宙刘,隨后出現(xiàn)的幾起案子苍姜,更是在濱河造成了極大的恐慌,老刑警劉巖悬包,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衙猪,死亡現(xiàn)場離奇詭異,居然都是意外死亡布近,警方通過查閱死者的電腦和手機(jī)垫释,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撑瞧,“玉大人棵譬,你說我怎么就攤上這事≡に牛” “怎么了茫船?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵琅束,是天一觀的道長。 經(jīng)常有香客問我算谈,道長,這世上最難降的妖魔是什么料滥? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任然眼,我火速辦了婚禮,結(jié)果婚禮上葵腹,老公的妹妹穿的比我還像新娘高每。我一直安慰自己,他們只是感情好践宴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布鲸匿。 她就那樣靜靜地躺著,像睡著了一般阻肩。 火紅的嫁衣襯著肌膚如雪带欢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天烤惊,我揣著相機(jī)與錄音乔煞,去河邊找鬼。 笑死柒室,一個(gè)胖子當(dāng)著我的面吹牛渡贾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播雄右,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼空骚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了擂仍?” 一聲冷哼從身側(cè)響起囤屹,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎防楷,沒想到半個(gè)月后牺丙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡复局,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年冲簿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亿昏。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡峦剔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出角钩,到底是詐尸還是另有隱情吝沫,我是刑警寧澤呻澜,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站惨险,受9級(jí)特大地震影響羹幸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜辫愉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一栅受、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧恭朗,春花似錦屏镊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至膀值,卻和暖如春棍丐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背虫腋。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工骄酗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人悦冀。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓趋翻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親盒蟆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子踏烙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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