Activity生命周期。
啟動(dòng)Activity: onCreate()—>onStart()—>onResume(),Activity進(jìn)入運(yùn)行狀態(tài)。
Activity退居后臺(tái): 當(dāng)前Activity轉(zhuǎn)到新的Activity界面或按Home鍵回到主屏: onPause()—>onStop(),進(jìn)入停滯狀態(tài)。
Activity返回前臺(tái): onRestart()—>onStart()—>onResume(),再次回到運(yùn)行狀態(tài)。
Activity退居后臺(tái),且系統(tǒng)內(nèi)存不足, 系統(tǒng)會(huì)殺死這個(gè)后臺(tái)狀態(tài)的Activity(此時(shí)這個(gè)Activity引用仍然處在任務(wù)棧中,只是這個(gè)時(shí)候引用指向的對(duì)象已經(jīng)為null),若再次回到這個(gè)Activity,則會(huì)走onCreate()–>onStart()—>onResume()(將重新走一次Activity的初始化生命周期)
鎖屏:
onPause()->onStop()解鎖:
onStart()->onResume()

通過(guò)Acitivty的xml標(biāo)簽來(lái)改變?nèi)蝿?wù)棧的默認(rèn)行為
- singleTop : 棧頂復(fù)用模式。這種模式下,如果新Activity已經(jīng)位于任務(wù)棧的棧頂,那么此Activity不會(huì)被重新創(chuàng)建,所以它的啟動(dòng)三回調(diào)就不會(huì)執(zhí)行,同時(shí)Activity的
onNewIntent()方法會(huì)被回調(diào)。如果Activity已經(jīng)存在但是不在棧頂,那么作用與standard模式一樣。 - singleTask: 棧內(nèi)復(fù)用模式。創(chuàng)建這樣的Activity的時(shí)候,系統(tǒng)會(huì)先確認(rèn)它所需任務(wù)棧已經(jīng)創(chuàng)建,否則先創(chuàng)建任務(wù)棧。然后放入Activity,如果棧中已經(jīng)有一個(gè)Activity實(shí)例,那么這個(gè)Activity就會(huì)被調(diào)到棧頂。
onNewIntent(),并且singleTask會(huì)清理在當(dāng)前Activity上面的所有Activity(clear top) - singleInstance : 加強(qiáng)版的singleTask模式,這種模式的Activity只能單獨(dú)位于一個(gè)任務(wù)棧內(nèi),由于棧內(nèi)復(fù)用的特性,后續(xù)請(qǐng)求均不會(huì)創(chuàng)建新的Activity,除非這個(gè)獨(dú)特的任務(wù)棧被系統(tǒng)銷(xiāo)毀了。
Activity的堆棧管理以ActivityRecord為單位,所有的ActivityRecord都放在一個(gè)List里面??梢哉J(rèn)為一個(gè)ActivityRecord就是一個(gè)Activity棧
Activity緩存方法
onSaveInstanceState()回調(diào)方法,一定會(huì)在Activity被回收之前調(diào)用。方法中有一個(gè)Bundle參數(shù),putString()、putInt()等方法需要傳入兩個(gè)參數(shù),一個(gè)鍵一個(gè)值。數(shù)據(jù)保存之后會(huì)在onCreate中恢復(fù),onCreate也有一個(gè)Bundle類型的參數(shù)。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//這里,當(dāng)Acivity第一次被創(chuàng)建的時(shí)候?yàn)榭? //所以我們需要判斷一下
if( savedInstanceState != null ){
savedInstanceState.getString("anAnt");
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("anAnt","Android");
}
-
onSavaInstanceState() 方法被調(diào)用的幾種情況
1.當(dāng)按下HOME鍵時(shí):
因?yàn)橄到y(tǒng)不知道你按下HOME鍵后要運(yùn)行多少其他的程序,自然也不知道Activity是否會(huì)被銷(xiāo)毀,故系統(tǒng)會(huì)調(diào)用onSaveInstanceState(),讓用戶有機(jī)會(huì)保存某些非永久性的數(shù)據(jù)。
2.按下多任務(wù)鍵,選擇運(yùn)行其他程序時(shí)。
3.按下電源鍵鎖屏?xí)r。
4.從當(dāng)前Activity中啟動(dòng)一個(gè)新的Activity時(shí)。
5.屏幕方向切換時(shí):
在屏幕切換之前系統(tǒng)會(huì)銷(xiāo)毀當(dāng)前Activity,在屏幕切換之后系統(tǒng)又會(huì)自動(dòng)地創(chuàng)建該Activity,所以該方法一定會(huì)被調(diào)用。
總而言之,onSaveInstanceState()的調(diào)用遵循的原則是:當(dāng)系統(tǒng)“未經(jīng)許可”銷(xiāo)毀了你的Activity時(shí),就會(huì)被調(diào)用。因?yàn)橄到y(tǒng)必須提供一個(gè)讓你保存數(shù)據(jù)的機(jī)會(huì)。
- 注意:
1.布局中的每一個(gè)View默認(rèn)實(shí)現(xiàn)了onSaveInstanceState()方法,這樣的話,這個(gè)UI的任何改變都會(huì)自動(dòng)地存儲(chǔ)和在activity重新創(chuàng)建的時(shí)候自動(dòng)地恢復(fù)。但是這種情況只有在你為這個(gè)UI提供了唯一的ID之后才起作用,如果沒(méi)有提供ID,app將不會(huì)存儲(chǔ)它的狀態(tài)。
2.由于onSaveInstanceState()方法調(diào)用的不確定性,你應(yīng)該只使用這個(gè)方法去記錄activity的瞬間狀態(tài)(UI的狀態(tài))。不應(yīng)該用這個(gè)方法去存儲(chǔ)持久化數(shù)據(jù)。當(dāng)用戶離開(kāi)這個(gè)activity的時(shí)候應(yīng)該在onPause()方法中存儲(chǔ)持久化數(shù)據(jù)(例如應(yīng)該被存儲(chǔ)到數(shù)據(jù)庫(kù)中的數(shù)據(jù))。
3.onSaveInstanceState()如果被調(diào)用,這個(gè)方法會(huì)在onStop()前被觸發(fā),但系統(tǒng)并不保證是否在onPause()之前或者之后觸發(fā)。
Fragment的生命周期以及與Activity之間的關(guān)系

注意和Activity相比的區(qū)別:
onAttach() onDetach()onCreateView() onDestoryView()
Intent的使用方法,可以傳遞哪些數(shù)據(jù)類型?
通過(guò)查詢Intent/Bundle的API文檔,我們可以知道,Intent/Bundle支持傳遞基本類型的數(shù)據(jù)和基本類型的數(shù)組數(shù)據(jù),以及String/CharSequence類型的數(shù)據(jù)和String/CharSequence類型的數(shù)組數(shù)據(jù)。而對(duì)于其他類型的數(shù)據(jù)或數(shù)組數(shù)據(jù)則可以使對(duì)象序列化,例如實(shí)現(xiàn)Parcelable接口或?qū)崿F(xiàn)Serializable接口。
為什么在Service中創(chuàng)建子線程而不是在Activity中?
這是因?yàn)锳ctivity很難對(duì)Thread進(jìn)行控制,當(dāng)Activity被銷(xiāo)毀之后,就沒(méi)有任何其它的辦法可以再重新獲取到之前創(chuàng)建的子線程的實(shí)例。而且在一個(gè)Activity中創(chuàng)建的子線程,另一個(gè)Activity無(wú)法對(duì)其進(jìn)行操作。但是Service就不同了,所有的Activity都可以與Service進(jìn)行關(guān)聯(lián),然后可以很方便地操作其中的方法,即使Activity被銷(xiāo)毀了,之后只要重新與Service建立關(guān)聯(lián),就又能夠獲取到原有的Service中Binder的實(shí)例。因此,使用Service來(lái)處理后臺(tái)任務(wù),Activity就可以放心地finish,完全不需要擔(dān)心無(wú)法對(duì)后臺(tái)任務(wù)進(jìn)行控制的情況。
Service的兩種啟動(dòng)方法是?有什么區(qū)別?
1.在Context中通過(guò)public boolean bindService(Intent service, ServiceConnectionconn, int flags)方法來(lái)進(jìn)行Service與Context的關(guān)聯(lián)并啟動(dòng),并且Service的生命周期依附于Context(不求同年同月同日生,但求同年同月同日死)。
2.通過(guò)public ComponentName startService(Intent service)方法去啟動(dòng)一個(gè)Service,此時(shí)Service的生命周期與啟動(dòng)它的Context無(wú)關(guān)。
3.要注意的是無(wú)論如何,都需要在AndroidManifest.xml里注冊(cè)你的Service
<service
android:name=".packnameName.youServiceName"
android:enabled="true" />
廣播(Broadcast Receiver)的兩種動(dòng)態(tài)注冊(cè)和靜態(tài)注冊(cè)有什么區(qū)別?
- 靜態(tài)注冊(cè):在AndroidManifest.xml文件中進(jìn)行注冊(cè),當(dāng)App退出后,Receiver仍然可以接收到廣播并且進(jìn)行相應(yīng)的處理。
- 動(dòng)態(tài)注冊(cè):在代碼中動(dòng)態(tài)注冊(cè),當(dāng)App退出后,也就沒(méi)辦法在接受廣播了。
保證Service不被殺死的幾種方法
1.Service設(shè)置成START_STICKY
- kill后會(huì)被重啟(等待5秒左右),重傳Intent,保持與重啟前一樣。
2.提升Service的優(yōu)先級(jí)
在AndroidManifest.xml文件中對(duì)于intent-file可以通過(guò)android:proiority = "1000"這個(gè)屬性設(shè)置最高優(yōu)先級(jí),1000是最高值,如果數(shù)字越小則優(yōu)先級(jí)越低,同樣適用于廣播。- 【結(jié)論】目前看來(lái),priority這個(gè)屬性貌似只適用于Broadcast,對(duì)于Service來(lái)說(shuō)無(wú)效。
3.onDestroy方法里重啟Service
- Service + Broadcast 方式,就是當(dāng)Service執(zhí)行onDestory()的時(shí)候,發(fā)送一個(gè)自定義的廣播,當(dāng)收到廣播的時(shí)候,重新啟動(dòng)service。
- 也可以直接在onDestroy()里startService
- 【結(jié)論】當(dāng)使用助手類軟件或者直接在設(shè)置里強(qiáng)制停止應(yīng)用時(shí),App進(jìn)程直接被結(jié)束,onDestroy方法都進(jìn)不來(lái),還是無(wú)法徹底保證。
4.監(jiān)聽(tīng)系統(tǒng)廣播判斷Service狀態(tài)
- 通過(guò)系統(tǒng)的一些廣播,比如:手機(jī)重啟、界面喚醒、應(yīng)用狀態(tài)改變等等監(jiān)聽(tīng)并捕獲到,然后判斷我們的Service是否還存活。
- 【結(jié)論】這也能算是一種措施,不過(guò)見(jiàn)聽(tīng)多了會(huì)導(dǎo)致Service很混亂,不方便。
5.root之后放到System/app變成系統(tǒng)級(jí)應(yīng)用
6.放一個(gè)像素在前臺(tái)
如何判斷應(yīng)用被強(qiáng)殺
在Application中定義一個(gè)Static常量,賦值為-1,在Splash界面改為0,如果被強(qiáng)殺,application重新初始化,在父類Activity判斷該常量的值。
應(yīng)用被強(qiáng)殺如何解決
如果在每一個(gè)Activity的onCreate里判斷是否被強(qiáng)殺,冗余了,封裝到Activity的父類中,如果被強(qiáng)殺,跳轉(zhuǎn)回主界面,如果沒(méi)有被強(qiáng)殺,執(zhí)行Activity的初始化操作,給主界面?zhèn)鬟fintent參數(shù),主界面會(huì)調(diào)用onNewIntent方法,在onNewIntent跳轉(zhuǎn)到歡迎頁(yè)面,重新來(lái)一遍流程。
Asset目錄與res目錄的區(qū)別
res 目錄下面有很多文件,例如 drawable,mipmap,raw 等。res 下面除了 raw 文件不會(huì)被壓縮外,其余文件都會(huì)被壓縮。同時(shí) res目錄下的文件可以通過(guò)R 文件訪問(wèn)。Asset 也是用來(lái)存儲(chǔ)資源,但是 asset 文件內(nèi)容只能通過(guò)路徑或者 AssetManager 讀取。
Android怎么加速啟動(dòng)Activity
啟動(dòng)應(yīng)用 :Application 的構(gòu)造方法,onCreate 方法中不要進(jìn)行耗時(shí)操作,數(shù)據(jù)預(yù)讀取(例如 init 數(shù)據(jù)) 放在異步中操作
啟動(dòng)普通的Activity:A 啟動(dòng)B 時(shí)不要在 A 的 onPause 中執(zhí)行耗時(shí)操作。因?yàn)?B 的 onResume 方法必須等待 A 的 onPause 執(zhí)行完成后才能運(yùn)行
Android內(nèi)存優(yōu)化方法:ListView優(yōu)化,及時(shí)關(guān)閉資源,圖片緩存等等。
View和View Group的區(qū)別?自定義View的過(guò)程?
Android的UI界面都是由View和ViewGroup及其派生類組合而成的。其中,View是所有UI組件的基類,而 ViewGroup是容納這些組件的容器,其本身也是從View派生出來(lái)的。View對(duì)象是Android平臺(tái)中用戶界面體現(xiàn)的基礎(chǔ)單位。View類是它稱為“widgets(工具)”的子類的基礎(chǔ),它們提供了諸如文本輸入框和按鈕之類的UI對(duì)象的完整實(shí)現(xiàn)。ViewGroup類同樣為其被稱為“Layouts(布局)”的子類奠定了基礎(chǔ),它們提供了象流式布局、表格布局以及相對(duì)布局之類的布局架構(gòu)。
-
如何自定義控件:
1.自定義屬性的聲明和獲取- 分析需要的自定義屬性
- 在res/values/attrs.xml定義聲明
- 在layout文件中進(jìn)行使用
- 在View的構(gòu)造方法中進(jìn)行獲取
2.測(cè)量onMeasure
3.布局onLayout(ViewGroup)
4.繪制onDraw
5.onTouchEvent
6.onInterceptTouchEvent(ViewGroup)
7.狀態(tài)的恢復(fù)與保存
Content的區(qū)別
- Activity和Service以及Application的Context是不一樣的,Activity繼承自ContextThemeWraper.其他的繼承自ContextWrapper
- 每一個(gè)Activity和Service以及Application的Context都是一個(gè)新的ContextImpl對(duì)象
- getApplication()用來(lái)獲取Application實(shí)例的,但是這個(gè)方法只有在Activity和Service中才能調(diào)用的到。那么也許在絕大多數(shù)情況下我們都是在Activity或者Service中使用Application的,但是如果在一些其它的場(chǎng)景,比如BroadcastReceiver中也想獲得Application的實(shí)例,這時(shí)就可以借助getApplicationContext()方法,getApplicationContext()比getApplication()方法的作用域會(huì)更廣一些,任何一個(gè)Context的實(shí)例,只要調(diào)用getApplicationContext()方法都可以拿到我們的Application對(duì)象。
- Activity在創(chuàng)建的時(shí)候會(huì)new一個(gè)ContextImpl對(duì)象并在attach方法中關(guān)聯(lián)它,Application和Service也差不多。ContextWrapper的方法內(nèi)部都是轉(zhuǎn)調(diào)ContextImpl的方法
- 創(chuàng)建對(duì)話框傳入Application的Context是不可以的
- 盡管Application、Activity、Service都有自己的ContextImpl,并且每個(gè)ContextImpl都有自己的mResources成員,但是由于它們的mResources成員都來(lái)自于唯一的ResourcesManager實(shí)例,所以它們看似不同的mResources其實(shí)都指向的是同一塊內(nèi)存
- Context的數(shù)量等于Activity的個(gè)數(shù) + Service的個(gè)數(shù) + 1,這個(gè)1為Application
IntentService的使用場(chǎng)景與特點(diǎn)
IntentService是Service的子類,是一個(gè)異步的,會(huì)自動(dòng)停止的服務(wù),很好解決了傳統(tǒng)的Service中處理完耗時(shí)操作忘記停止并銷(xiāo)毀Service的問(wèn)題
優(yōu)點(diǎn):
- 一方面不需要自己去new Thread
- 另一方面不需要考慮在什么時(shí)候關(guān)閉該Service
onStartCommand中回調(diào)了onStart,onStart中通過(guò)mServiceHandler發(fā)送消息到該handler的handleMessage中去。最后handleMessage中回調(diào)onHandleIntent(intent)。