2.1 Activity
1.Activity是什么?
Activity是Android的四大組件之一。是用戶操作的可視化界面;它為用戶提供了一個完成操作指令的窗口。
當我們創建完畢Activity之后,需要調用setContentView()方法來完成界面的顯示;以此來為用戶提供交互的入口。
2.典型情況下的Activity生命周期?
Activity啟動–>onCreate()–>onStart()–>onResume()
點擊home鍵回到桌面–>onPause()–>onStop()
再次回到原Activity時–>onRestart()–>onStart()–>onResume()
退出當前Activity時–>onPause()–>onStop()–>onDestroy()
3.異常情況下的Activity的生命周期 & 數據如何保存和恢復?
在onStop之前調用onSaveInstanceState保存當前Activity狀態,當Activity被重新創建后,系統調用
onRestoreInstanceState,並且把Activity銷毀時onSaveInstanceState方法所保存的Bundle對象
作為參數傳遞給onRestoreInstanceState和onCreate方法
onRestoreInstanceState的調用時機發生在onStart之后
4.從Activity A跳轉到Activity B之后,然后再點擊back鍵之后,它們的生命周期調用流程是什么?
從Activity A跳轉到Activity B
Activity A -> onPause()
Activity B -> onCreate()
Activity B -> onStart()
Activity B -> onResume()
Activity A -> onStop()
點擊back鍵
Activity B -> onPause()
Activity A -> onRestart()
Activity A -> onStart()
Activity A -> onResume()
Activity B -> onStop()
Activity B -> onDestroy()
5.如何統計Activity的工作時間?
Activity開始工作的起點是onResume()而工作的停止點為onPause(),
因此當每次Activity調用onResume()的時候記錄一個時間a,每次調用onPause()的時候再記錄一個時間b,
那么由b-a可得當次Activity工作的時間。
6.給我說說Activity的啟動模式 & 使用場景。
系統默認的啟動模式:standard
系統的默認模式,每次啟動一個Activity都會重新創建一個新的實例
棧頂復用模式:singleTop
如果在任務的棧頂正好存在該Activity的實例,就重用該實例( 會調用實例的 onNewIntent() ),
否則就會創建新的實例並放入棧頂,即使棧中已經存在該Activity的實例,只要不在棧頂,都會創建新的實例。
使用場景如新聞類或者閱讀類App的內容頁面。
棧內復用模式:singleTask
如果在棧中已經有該Activity的實例,就重用該實例(會調用實例的 onNewIntent() )。
重用時,會讓該實例回到棧頂,因此在它上面的實例將會被移出棧。如果棧中不存在該實例,將會創建新的實例放入棧中。
使用場景如瀏覽器的主界面。不管從多少個應用啟動瀏覽器,只會啟動主界面一次,其余情況都會走onNewIntent,
並且會清空主界面上面的其他頁面。
單實例模式:singleInstance
在一個新棧中創建該Activity的實例,並讓多個應用共享該棧中的該Activity實例。
一旦該模式的Activity實例已經存在於某個棧中,任何應用再激活該Activity時都會重用該棧中的實例
( 會調用實例的 onNewIntent() )。其效果相當於多個應用共享一個應用,不管誰激活該 Activity 都會進入同一個應用中。
使用場景如鬧鈴提醒,將鬧鈴提醒與鬧鈴設置分離。singleInstance不要用於中間頁面,如果用於中間頁面,跳轉會有問題,
比如:A -> B (singleInstance) -> C,完全退出后,在此啟動,首先打開的是B。
7.如何在任意位置關掉應用所有Activity & 如何在任意位置關掉指定的Activity?
封裝一個類,成員變量有一個List集合,當Activity執行onCreate()方法時將當前的Activity實例加入,
遍歷這個List且逐一調用finish()即可
給每個啟動的Activity一個tag,根據這個tag和集合可達到在任意位置關閉指定Activity的效果。
8.Activity的啟動流程(從源碼角度解析)?
app啟動的過程有兩種情況,第一種是從桌面launcher上點擊相應的應用圖標,
第二種是在activity中通過調用startActivity來啟動一個新的activity。
我們創建一個新的項目,默認的根activity都是MainActivity,而所有的activity都是保存在堆棧中的,
我們啟動一個新的activity就會放在上一個activity上面,而我們從桌面點擊應用圖標的時候,由於launcher本身也是一個應用,
當我們點擊圖標的時候,系統就會調用startActivitySately(),一般情況下,我們所啟動的activity的相關信息都會保存在intent中,
比如action,category等等。我們在安裝這個應用的時候,系統也會啟動一個PackaManagerService的管理服務,
這個管理服務會對AndroidManifest.xml文件進行解析,從而得到應用程序中的相關信息,比如service,activity,Broadcast等等,然后獲得相關組件的信息。
當我們點擊應用圖標的時候,就會調用startActivitySately()方法,而這個方法內部則是調用startActivty(),
而startActivity()方法最終還是會調用startActivityForResult()這個方法。
因為startActivityForResult()方法是有返回結果的,所以系統就直接給一個-1,就表示不需要結果返回了。
而startActivityForResult()這個方法實際是通過Instrumentation類中的execStartActivity()方法來啟動activity,
Instrumentation這個類主要作用就是監控程序和系統之間的交互。而在這個execStartActivity()方法中會獲取ActivityManagerService的代理對象,
通過這個代理對象進行啟動activity。啟動會就會調用一個checkStartActivityResult()方法,如果說沒有在配置清單中配置有這個組件,就會在這個方法中拋出異常了。
當然最后是調用的是Application.scheduleLaunchActivity()進行啟動activity,而這個方法中通過獲取得到一個ActivityClientRecord對象,
而這個ActivityClientRecord通過handler來進行消息的發送,系統內部會將每一個activity組件使用ActivityClientRecord對象來進行描述,
而ActivityClientRecord對象中保存有一個LoaderApk對象,通過這個對象調用handleLaunchActivity來啟動activity組件,
而頁面的生命周期方法也就是在這個方法中進行調用。
9.啟動一個其它應用的Activity的生命周期分析。
同4
10.Activity任務棧是什么?在項目中有用到它嗎?說給我聽聽
-android任務棧又稱為Task,它是一個棧結構,具有后進先出的特性,用於存放我們的Activity組件。
-我們每次打開一個新的Activity或者退出當前Activity都會在一個稱為任務棧的結構中添加或者減少一個Activity組件,因此一個任務棧包含了一個activity的集合, android系統可以通過Task有序地管理每個activity,並決定哪個Activity與用戶進行交互:只有在任務棧棧頂的activity才可以跟用戶進行交互。
-在我們退出應用程序時,必須把所有的任務棧中所有的activity清除出棧時,任務棧才會被銷毀。當然任務棧也可以移動到后台, 並且保留了每一個activity的狀態. 可以有序的給用戶列出它們的任務, 同時也不會丟失Activity的狀態信息。
-需要注意的是,一個App中可能不止一個任務棧,某些特殊情況下,單獨一個Actvity可以獨享一個任務棧。還有一點就是一個Task中的Actvity可以來自不同的App,同一個App的Activity也可能不在一個Task中。
11.什么情況下Activity不走onDestory?
當 Activity 被另外一個 Activity 覆蓋、失去焦點並不可見時處於 Stoped 狀態。
9.0的時候如果強行終止activity,那么也不會執行onDestory
12.什么情況下Activity會單獨執行onPause?
同11
13.a->b->c界面,其中b是SingleInstance的,那么c界面點back返回a界面,為什么?
SingleInstance 這是一種加強的singleTask模式,它除了具有singleTask模式所有的特性外,還加強了一點,那就是具有此種模式的Activity只能單獨位於一個任務棧中,換句話說,比如Activity A是singleInstance模式,當A啟動后,系統會為它創建一個新的任務棧,然后A獨自在這個新的任務棧中,由於棧內復用的特性,后續的請求均不會創建新的Activity,除非這個獨特的任務棧被系統銷毀了
14.如果一個Activity彈出一個Dialog,那么這個Acitvity會回調哪些生命周期函數呢?
是否彈出 Dialog,並不影響 Activity 的生命周期,所以這時和正常啟動時 Activity 的生命回調方法一致: onCreate() -> onStart() -> onResume()。
15.Activity之間如何通信 & Activity和Fragment之間通信 & Activity和Service之間通信?
1.Activity->Activity
[1]Intent/Bundle
這種方式多用於Activity之間傳遞數據
[2]類靜態變量
在Activity內部定義靜態的變量,這種方式見於少量的數據通信,如果數據過多,還是使用第一種方式
[3]全局變量
創建一個類,里面定義一批靜態變量,Activity之間通信都可以訪問這個類里面的靜態變量,這就是全局變量。
2.Activity->Service
[1]綁定服務的方式,利用ServiceConnection這個接口
[2]Intent
這種方式很簡單,我們在啟動和停止Service時所調用的方法都需要傳入一個Intent實例對象,通過這個傳入的Intent對象,我們就可以與Service進行通信。
[3]CallBack + Handler,監聽服務的進程變化
3.Activity->Fragment
[1]Bundle
在創建Fragment實例的時候,調用方法setArguments將一個Bundle對象傳遞給Fragment,然后在Fragment中先去判斷是否和當前Activity綁定上了,如果綁定上了,就可以拿出這個Bundle中的數據
[2]直接進行方法調用
在Activity里通過Fragment的引用,可以直接調用Framgent中的定義的任何方法。
16.說說Activity橫豎屏切換的生命周期。
onPause
onSaveInstanceState //這里可以用來橫豎屏切換的保存數據
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState//這里可以用來橫豎屏切換的恢復數據
onResume
17.前台切換到后台,然后在回到前台時Activity的生命周期。
點擊home鍵回到桌面–>onPause()–>onStop()
再次回到原Activity時–>onRestart()–>onStart()–>onResume()
18.下拉狀態欄時Activity的生命周期?
首先,通知欄下拉一點點,符合一般描述中“Activity被部分遮擋”——onPause()
然后,通知欄完全落下之后,“Activity被全部遮擋”——onStop()
19.Activity與Fragment的生命周期比較?
onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume();
Fragment變為不可見狀態(鎖屏、回到桌面、被Activity完全覆蓋):onPause()->onSaveInstanceState()->onStop();
Fragment變為部分可見狀態(打開Dialog樣式的Activity):onPause()->onSaveInstanceState();
Fragment由不可見變為活動狀態:onStart()->OnResume();
Fragment由部分可見變為活動狀態:onResume();
退出應用:onPause()->onStop()->onDestroyView()->onDestroy()->onDetach()
Fragment被回收又重新創建:被回收執行onPause()->onSaveInstanceState()->onStop()->onDestroyView()->onDestroy()->onDetach(),重新創建執行onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume()->setUserVisibleHint();
橫豎屏切換:與Fragment被回收又重新創建一樣。
20.了解哪些Activity常用的標記位Flags?
1.Intent.FLAG_ACTIVITY_NEW_TASK,是為Activity指定“singleTask”啟動模式
2.Intent.FLAG_ACTIVITY_SINGLE_TOP,是為Activity指定“singleTop”啟動模式
3.FLAG_ACTIVITY_CLEAR_TOP,如果跟singleTask啟動模式一起出現,如果被啟動的Activity已經存在實例,則onNewIntent方法會被回調,如果被啟動的Activity采用standard模式啟動,那么連同它跟它之上的Activity都要出棧,並且創建新的實例放入棧頂。
4.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,新的Activity不會在最近啟動的Activity的列表中保存。等同於指定屬性android:excludeFromRecents="true"
21.談談隱式啟動和顯示啟動Activity的方式?
顯式啟動:直接指定要跳轉的Activity類名,不用過濾,效率高,適用於同一個應用中的不同Activity跳轉
隱式啟動:需要過濾,相對耗時,但可以找到所有之匹配的應用。適用於不同應用之間的Activity跳轉。
隱式啟動會找到所匹配到的應用,並提示用戶選擇打開方式,如果有多個組件被匹配成功,就會以對話框列表的方式讓用戶進行選擇。
22.Activity用Intent傳遞數據和Bundle傳遞數據的區別?為什么不用HashMap呢?
要把值通過A經過B傳給C
如果用Intent的話 A-B先寫一遍 再在B中都取出來 然后在把值塞到Intent中 再跳到C 累嗎?
如果我在A中用了 Bundle 的話 我把Bundle傳給B 在B中再轉傳到C C就可以直接去了
這樣的話 還有一個好處 就是在B中 還可以給Bundle對象添加新的 key - value 同樣可以在C中取出來
為什么不用HashMap呢?
Bundle內部是由ArrayMap實現的,ArrayMap的內部實現是兩個數組,一個int數組是存儲對象數據對應下標,一個對象數組保存key和value,內部使用二分法對key進行排序,所以在添加、刪除、查找數據的時候,都會使用二分法查找,只適合於小數據量操作,如果在數據量比較大的情況下,那么它的性能將退化。而HashMap內部則是數組+鏈表結構,所以在數據量較少的時候,HashMap的Entry Array比ArrayMap占用更多的內存。因為使用Bundle的場景大多數為小數據量
在Android中如果使用Intent來攜帶數據的話,需要數據是基本類型或者是可序列化類型,HashMap使用Serializable進行序列化,而Bundle則是使用Parcelable進行序列化。而在Android平台中,更推薦使用Parcelable實現序列化,雖然寫法復雜,但是開銷更小,所以為了更加快速的進行數據的序列化和反序列化,系統封裝了Bundle類,方便我們進行數據的傳輸。
23.在隱式啟動中Intent可以設置多個action,多個category嗎 & 順便講講它們的匹配規則?
一個Intent對象中最多只能包括一個Action屬性,但可以包含多個Category屬性
24.Activity可以設置為對話框的形式嗎?
在mainifest中對應的activity上配置如下的代碼,即可讓activity以對話框的方式表現出來
< android:theme="@android:style/Theme.Dialog">
25.如何給Activity設置進入和退出的動畫?
一種是直接在代碼中設置,這需要使用到Activity的overridePendingTransition方法;
另一種是通過自定義Activity的主題來實現。
26.Activity使用Intent傳遞數據是否有限制 & 如果傳遞一個復雜的對象,例如一個復雜的控件對象應該怎么做?
1 傳512K以下的數據的數據可以正常傳遞。
2 傳512K~1024K的數據會出錯,閃退。
3 傳1024K以上的數據會報錯:TransactionTooLargeException。
4 考慮到Intent還包括要啟動的Activity等信息,實際可以傳的數據略小於512K
如果傳遞一個復雜的對象,例如一個復雜的控件對象應該怎么做?
1)將對象轉換為Json字符串
2)使用Serializable,Parcelable序列化對象
1.Serializable實現:
①業務Bean實現:Serializable接口,寫上getter和setter方法
②Intent通過調用putExtra(String name, Serializable value)傳入對象實例 當然對象有多個的話多個的話,我們也可以先Bundle.putSerializable(x,x);
③新Activity調用getSerializableExtra()方法獲得對象實例: eg:Product pd = (Product) getIntent().getSerializableExtra("Product");
④調用對象get方法獲得相應參數
2.Parcelable實現:
一般流程:
①業務Bean繼承Parcelable接口,重寫writeToParcel方法,將你的對象序列化為一個Parcel對象;
②重寫describeContents方法,內容接口描述,默認返回0就可以
③實例化靜態內部對象CREATOR實現接口Parcelable.Creator
④同樣式通過Intent的putExtra()方法傳入對象實例,當然多個對象的話,我們可以先 放到Bundle里Bundle.putParcelable(x,x),再Intent.putExtras()即可
3.使用數據庫
2.2 BroadcastReceiver
1.廣播是什么?
它是一種廣泛運用在應用程序之間傳輸信息的機制,Android中我們發送廣播內容是一個Intent,這個Intent中可以攜帶我們要發送的數據。
2.廣播的注冊方式有哪些?
1 靜態注冊:創建一個廣播接收器類,廣播接收器在AndroidManifest.xml文件中注冊
2 動態注冊:新建一個類,讓它繼承自BroadcastReceiver,並重寫父類的onReceive()方法就行了
3.廣播的分類 & 特性 & 使用場景?
3.1 無序廣播
context.sendBroadcast(Intent)方法發送的廣播,不可被攔截,當然發送的數據,接收者是不能進行修改的。
3.2 有序廣播
context.sendOrderBroadcast(Intent)方法發送的廣播,可被攔截,而且接收者是可以修改其中要發送的數據,修改和添加都是可以的,這就意味着優先接收者對數據修改之后,下一個接收者接受的數據是上一個接收者已經修改了的,這必須明白。
3.3 本地廣播
localBroadcastManager.sendBroadcast(Intent),只在app內傳播。
4.說說系統廣播和本地廣播的原理 & 區別 & 使用場景。
4.1 系統廣播的源碼角度分析
a.自定義廣播接收者BroadcastReceiver,並且重寫onReceiver()方法。
b.通過Binder機制向AMS(Activity Manager Service)進行注冊。
c.廣播發送者通過Binder機制向AMS發送廣播。
d.AMS查找符合條件(IntentFilter/Permission等)的BroadcastReceiver,將廣播發送到相應的BroadcastReceiver(一般情況下是Activity)的消息隊列中。
e.消息循環執行拿到此廣播,回調BroadcastReceiver中的onReceiver()方法。
4.2 本地廣播的源碼角度分析
相比於系統廣播而言,本地廣播更加安全,更加高效,以下是本地廣播的特點以及內部的實現機制:
特點:
a.使用它發送的廣播將只在自身app內傳播,因此你不必擔心泄漏隱私的數據。
b.其他app無法對你的app發送該廣播,因此你的app根本不可能收到非自身app發送的該廣播,因此你不必擔心有安全漏洞可以利用。
c.比系統廣播更加高效。
5.有兩個應用注冊了一樣的廣播,一個是靜態,一個是動態,連優先級也一樣,那么當廣播從系統發出來后,哪個應用先接收到廣播?
動態注冊的接收者會先執行
2.3 ContentProvider
1.什么是內容提供者?
(Content Provider)主要用於在不同的應用程序之間實現數據共享的功能
2.說說如何創建自己應用的內容提供者 & 使用場景。
新建一個類去繼承ContentProvider類的方式來創建一個自己的內容提供器。ContentProvider類有6個抽象方法,我們在使用子類繼承它的時候,需要將這6個方法全部重寫。
3.說說ContentProvider的原理。
一種進程間通信的方式,其實它原理核心就是Binder。
4.ContentProvider,ContentResolver,ContentObserver之間的關系?
ContentProvider——內容提供者, 在android中的作用是對外共享數據,也就是說你可以通過
ContentProvider把應用中的數據共享給其他應用訪問,其他應用可以通過ContentProvider 對你應用中的數據進行添刪改查。
ContentResolver——內容解析者, 其作用是按照一定規則訪問內容提供者的數據(其實就是調用內容提供者自定義的接口來操作它的數據)。 ContentObserver——內容觀察者,目的是觀察(捕捉)特定Uri引起的數據庫的變化,繼而做一些相應的處理,它類似於數據庫技術中的觸發器(Trigger),當ContentObserver所觀察的Uri發生變化時,便會觸發它
5.說說ContentProvider的權限管理。
android:grantUriPermssions:臨時許可標志。
android:permission:Provider讀寫權限。
android:readPermission:Provider的讀權限。
android:writePermission:Provider的寫權限。
android:enabled:標記允許系統啟動Provider。
android:exported:標記允許其他應用程序使用這個Provider。
android:multiProcess:標記允許系統啟動Provider相同的進程中調用客戶端。
2.4 Service
1.什么是Service?
Service(服務)是一個一種可以在后台執行長時間運行操作而沒有用戶界面的組件。它運行於UI線程,因此不能進行耗時的操作。
2.說說Service的生命周期。
bindService:onCreate()-onBind()-unBind()-onDestroy()
這種方式進行啟動service好處是更加便利activity中操作service,通過ServiceConnection來獲取service中內部類的類對象,然后通過這個類對象就可以調用類中的方法
startService:onCreate()-onStartCommon()-onDestroy()
當我們通過startService被調用以后,多次在調用startService(),onCreate()方法也只會被調用一次,而onStartConmon()會被多次調用
3.Service和Thread的區別?
Service的運行是在UI線程當中的,是絕對絕對不能進行耗時操作的,而Thread開啟的子線程則可以進行耗時操作,但是Thread開啟的子線程是不能直接對UI進行操作的,否則極有可能發生直接讓程序崩掉,這就是它們的區別。
4.Android 5.0以上的隱式啟動問題及其解決方案。
1 將隱式啟動轉換為顯式啟動,兼容編譯sdk5.0以后版本
2 直接寫上包名以及標志
3 判斷應用是否安裝
5.給我說說Service保活方案
1)onStartCommand方法,返回START_STICKY
2)提升service優先級
在AndroidManifest.xml文件中對於intent-filter可以通過android:priority = "1000"這個屬性設置最高優先級,1000是最高值,如果數字越小則優先級越低,同時適用於廣播。
3)提升service進程優先級
Android中的進程是托管的,當系統進程空間緊張的時候,會依照優先級自動進行進程的回收。Android將進程分為6個等級,它們按優先級順序由高到低依次是:
復制代碼
1.前台進程( FOREGROUND_APP)
2.可視進程(VISIBLE_APP )
3.次要服務進程(SECONDARY_SERVER )
4.后台進程 (HIDDEN_APP)
5.內容供應節點(CONTENT_PROVIDER)
6.空進程(EMPTY_APP)
4)onDestroy方法里重啟service
5)Application加上Persistent屬性
6.IntentService是什么 & 原理 & 使用場景 & 和Service的區別。
IntentService是繼承處理異步請求的一個類,在IntentService內有一個工作線程來處理耗時操作,啟動IntentServiced的方式和啟動傳統的Service一樣,同時,當任務執行完成后,IntentService會自動停止,而不需要我們手動去控制或stopSelf()。
a.它本質是一種特殊的Service,繼承自Service並且本身就是一個抽象類。
b.它內部是由HandlerThread和Handler實現異步操作。
7.創建一個獨立進程的Service應該怎樣做?
創建遠程服務
1)定義AIDL接口
2)新建Remote Service
3)在AndroidManifest.xml中對Remote Service進行配置
8.Service和Activity之間如何通信?
1、Intent傳值,onStartCommand()接收。
2、通過onBind()獲取Service實例,然后再調用Binder中的相關方法。
3、通過回調函數達到偵聽Service中數據變化。
9.說說你了解的系統Service。
https://blog.csdn.net/geyunfei_/article/details/78851024
10.談談你對ActivityManagerService的理解。
從系統運行的角度看,AmS可以分為Client端和Service端:Client端運行在各個app進程,app進程實現了具體的Activity,Service等,告訴系統我有那些Activity,Service等,並且調用系統接口來完成顯示;Service端運行在SystemServer進程,是系統級別的ActivityManagerService的具體實現,其響應Client端的系統調用請求,並且管理Client端各個app進程的生命周期。
https://www.cnblogs.com/xingchenkn/p/3637137.html
11.在Activtiy中創建一個Thread和在一個Service中創建一個Thread的區別?
Activtiy中的線程是前台線程,它的生命周期往往是隨着Activity的,Activity銷毀的時候,那個線程也應該被銷毀,否則就會出現內存泄漏現象。而Service中開啟的線程,它是工作在后台的,一般來講,后台線程的生存期是比較長的。
2.5 Handler
1.子線程一定不能更新UI嗎?
是否有些控件支持在子線程更新UI呢?比如:SurfaceViw
在Activity的onResume()生命周期函數之前是可以在子線程中更新UI的。
2.給我說說Handler的原理
Message:消息,其中包含了消息ID,消息處理對象以及處理的數據等,由MessageQueue統一列隊,終由Handler處理。
Handler:處理者,負責Message的發送及處理。使用Handler時,需要實現handleMessage(Message msg)方法來對特定的Message進行處理,例如更新UI等。
MessageQueue:消息隊列,用來存放Handler發送過來的消息,並按照FIFO規則執行。當然,存放Message並非實際意義的保存,而是將Message以鏈表的方式串聯起來的,等待Looper的抽取。
Looper:消息泵,不斷地從MessageQueue中抽取Message執行。因此,一個MessageQueue需要一個Looper。
Thread:線程,負責調度整個消息循環,即消息循環的執行場所。
Handler是可以通過發送和處理Message和Runnable對象來關聯相應線程的MessageQueue。通常我們認為它是一種異步機制。
a.可以讓對應的Message和Runnable在未來的某個時間點進行相應的處理。
b.讓自己想要的耗時操作在子線程中完成,讓更新UI的操作在主線程中完成,而子線程與主線程之間的通信就是靠Handler來完成。
3.Handler導致的內存泄露你是如何解決的?
Handler導致內存泄漏的原因是:非靜態內部類持有外部類的引用,導致外部類在沒有被使用的時候,遲遲不能被回收,從而導致內存泄漏。即非靜態Handler內部類持有外部Activity的引用,導致外部Activity退出/銷毀的時候,它遲遲不能被回收,最終導致Activity的內存泄漏。 解決方法:將Handler類聲明為靜態,如果Handler需要訪問外部類Activity的成員變量或者成員方法,可以用弱引用的方式解決。
4.如何使用Handler讓子線程和子線程通信?
在ThreadA中准備一個Looper,也就是消息輪詢大管家,然后准備發送消息的Handler,准備發送消息的Handler很容易理解,那就是在ThreadA中生成一個Handler對象即可,
那么准備Looper怎么做呢?在ThreadA中調用Looper.prepare(),然后再調用Looper.loop()即可
5.你能給我說說Handler的設計原理?
6.HandlerThread是什么 & 原理 & 使用場景?
a.HandlerThread本質上是一個線程類,它繼承了Thread。
b.HandlerThread有自己內部的Looper對象,可以進行Looper循環。
c.通過獲取HandlerThread的Looper對象傳遞給Handler對象,可以在handlerMessage方法中執行異步任務。
d.優點是不會有堵塞,減少對性能的消耗,缺點是不能進行多任務的處理,需要等待進行處理,處理效率較低。
e.與線程池注重並發不同,HandlerThread是一個串行隊列,HandlerThread背后只有一個線程
7.IdleHandler是什么?
IdleHandler 可以用來提升性能,主要用在我們希望能夠在當前線程消息隊列空閑時做些事情(譬如 UI 線程在顯示完成后,如果線程空閑我們就可以提前准備其他內容)的情況下,不過最好不要做耗時操作。
8.一個線程能否創建多個Handler,Handler和Looper之間的對應關系?
一個線程可以有多個Handler,但是一個線程只能有一個Looper,一個MessageQueue。因此它們之間的關系是一個線程只能有一個Looper,一個MessageQueue,多個Handler。
9.為什么Android系統不建議子線程訪問UI?
UI控件不是線程安全的,如果多線程並發訪問UI控件可能會出現不可預期的狀態
那為什么系統不對UI控件的訪問加上鎖機制呢?
加上鎖機制會讓UI訪問的邏輯變得復雜; 鎖機制會降低UI訪問的效率,因為鎖機制會阻塞某些線程的執行;
10.Looper死循環為什么不會導致應用卡死?
ActivityThread的main方法主要就是做消息循環,一旦退出消息循環,那么你的應用也就退出了。
11.使用Handler的postDealy后消息隊列有什么變化?
https://blog.csdn.net/qingtiantianqing/article/details/72783952
12.可以在子線程直接new一個Handler出來嗎?
1(需先在該線程中手動開啟Looper(Looper.prepare()-->Looper.loop()),然后將其綁定到Handler對象上
2(通過Looper.getMainLooper(),獲得主線程的Looper,將其綁定到此Handler對象上
13.Message對象創建的方式有哪些 & 區別?
https://blog.csdn.net/dfskhgalshgkajghljgh/article/details/52672115