Activity生命周期郑藏。
啟動Activity: onCreate()—>onStart()—>onResume()确徙,Activity進入運行狀態(tài)镇饺。
Activity退居后臺: 當前Activity轉(zhuǎn)到新的Activity界面或按Home鍵回到主屏: onPause()—>onStop()愿卸,進入停滯狀態(tài)抄瓦。
Activity返回前臺: onRestart()—>onStart()—>onResume(),再次回到運行狀態(tài)蚕泽。
Activity退居后臺晌梨,且系統(tǒng)內(nèi)存不足, 系統(tǒng)會殺死這個后臺狀態(tài)的Activity(此時這個Activity引用仍然處在任務棧中须妻,只是這個時候引用指向的對象已經(jīng)為null)仔蝌,若再次回到這個Activity,則會走onCreate()–>onStart()—>onResume()(將重新走一次Activity的初始化生命周期)
鎖屏:
onPause()->onStop()
解鎖:
onStart()->onResume()
通過Acitivty的xml標簽來改變?nèi)蝿諚5哪J行為
- singleTop : 棧頂復用模式。這種模式下荒吏,如果新Activity已經(jīng)位于任務棧的棧頂敛惊,那么此Activity不會被重新創(chuàng)建,所以它的啟動三回調(diào)就不會執(zhí)行绰更,同時Activity的
onNewIntent()
方法會被回調(diào)瞧挤。如果Activity已經(jīng)存在但是不在棧頂,那么作用與standard模式一樣儡湾。 - singleTask: 棧內(nèi)復用模式特恬。創(chuàng)建這樣的Activity的時候,系統(tǒng)會先確認它所需任務棧已經(jīng)創(chuàng)建徐钠,否則先創(chuàng)建任務棧癌刽。然后放入Activity,如果棧中已經(jīng)有一個Activity實例尝丐,那么這個Activity就會被調(diào)到棧頂显拜。
onNewIntent()
,并且singleTask會清理在當前Activity上面的所有Activity(clear top) - singleInstance : 加強版的singleTask模式摊崭,這種模式的Activity只能單獨位于一個任務棧內(nèi)讼油,由于棧內(nèi)復用的特性,后續(xù)請求均不會創(chuàng)建新的Activity呢簸,除非這個獨特的任務棧被系統(tǒng)銷毀了矮台。
Activity的堆棧管理以ActivityRecord為單位,所有的ActivityRecord都放在一個List里面根时∈莺眨可以認為一個ActivityRecord就是一個Activity棧
Activity緩存方法
onSaveInstanceState()
回調(diào)方法,一定會在Activity被回收之前調(diào)用蛤迎。方法中有一個Bundle參數(shù)确虱,putString()、putInt()等方法需要傳入兩個參數(shù)替裆,一個鍵一個值校辩。數(shù)據(jù)保存之后會在onCreate中恢復窘问,onCreate也有一個Bundle類型的參數(shù)。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//這里宜咒,當Acivity第一次被創(chuàng)建的時候為空
//所以我們需要判斷一下
if( savedInstanceState != null ){
savedInstanceState.getString("anAnt");
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("anAnt","Android");
}
-
onSavaInstanceState() 方法被調(diào)用的幾種情況
1.當按下HOME鍵時:
因為系統(tǒng)不知道你按下HOME鍵后要運行多少其他的程序惠赫,自然也不知道Activity是否會被銷毀,故系統(tǒng)會調(diào)用onSaveInstanceState()
故黑,讓用戶有機會保存某些非永久性的數(shù)據(jù)儿咱。
2.按下多任務鍵,選擇運行其他程序時场晶。
3.按下電源鍵鎖屏時混埠。
4.從當前Activity中啟動一個新的Activity時。
5.屏幕方向切換時:
在屏幕切換之前系統(tǒng)會銷毀當前Activity诗轻,在屏幕切換之后系統(tǒng)又會自動地創(chuàng)建該Activity钳宪,所以該方法一定會被調(diào)用。
總而言之概耻,onSaveInstanceState()
的調(diào)用遵循的原則是:當系統(tǒng)“未經(jīng)許可”銷毀了你的Activity時使套,就會被調(diào)用罐呼。因為系統(tǒng)必須提供一個讓你保存數(shù)據(jù)的機會鞠柄。
- 注意:
1.布局中的每一個View默認實現(xiàn)了onSaveInstanceState()
方法,這樣的話嫉柴,這個UI的任何改變都會自動地存儲和在activity重新創(chuàng)建的時候自動地恢復厌杜。但是這種情況只有在你為這個UI提供了唯一的ID之后才起作用,如果沒有提供ID计螺,app將不會存儲它的狀態(tài)夯尽。
2.由于onSaveInstanceState()
方法調(diào)用的不確定性,你應該只使用這個方法去記錄activity的瞬間狀態(tài)(UI的狀態(tài))登馒。不應該用這個方法去存儲持久化數(shù)據(jù)匙握。當用戶離開這個activity的時候應該在onPause()
方法中存儲持久化數(shù)據(jù)(例如應該被存儲到數(shù)據(jù)庫中的數(shù)據(jù))。
3.onSaveInstanceState()
如果被調(diào)用陈轿,這個方法會在onStop()
前被觸發(fā)圈纺,但系統(tǒng)并不保證是否在onPause()
之前或者之后觸發(fā)。
Fragment的生命周期以及與Activity之間的關(guān)系
注意和Activity相比的區(qū)別:
onAttach() onDetach()
onCreateView() onDestoryView()
Intent的使用方法麦射,可以傳遞哪些數(shù)據(jù)類型蛾娶?
通過查詢Intent/Bundle的API文檔,我們可以知道潜秋,Intent/Bundle支持傳遞基本類型的數(shù)據(jù)和基本類型的數(shù)組數(shù)據(jù)蛔琅,以及String/CharSequence類型的數(shù)據(jù)和String/CharSequence類型的數(shù)組數(shù)據(jù)。而對于其他類型的數(shù)據(jù)或數(shù)組數(shù)據(jù)則可以使對象序列化峻呛,例如實現(xiàn)Parcelable接口或?qū)崿F(xiàn)Serializable接口罗售。
為什么在Service中創(chuàng)建子線程而不是在Activity中辜窑?
這是因為Activity很難對Thread進行控制,當Activity被銷毀之后寨躁,就沒有任何其它的辦法可以再重新獲取到之前創(chuàng)建的子線程的實例谬擦。而且在一個Activity中創(chuàng)建的子線程,另一個Activity無法對其進行操作朽缎。但是Service就不同了惨远,所有的Activity都可以與Service進行關(guān)聯(lián),然后可以很方便地操作其中的方法话肖,即使Activity被銷毀了北秽,之后只要重新與Service建立關(guān)聯(lián),就又能夠獲取到原有的Service中Binder的實例最筒。因此贺氓,使用Service來處理后臺任務,Activity就可以放心地finish床蜘,完全不需要擔心無法對后臺任務進行控制的情況辙培。
Service的兩種啟動方法是?有什么區(qū)別邢锯?
1.在Context中通過public boolean bindService(Intent service, ServiceConnectionconn, int flags)
方法來進行Service與Context的關(guān)聯(lián)并啟動扬蕊,并且Service的生命周期依附于Context(不求同年同月同日生,但求同年同月同日死)丹擎。
2.通過public ComponentName startService(Intent service)
方法去啟動一個Service尾抑,此時Service的生命周期與啟動它的Context無關(guān)。
3.要注意的是無論如何蒂培,都需要在AndroidManifest.xml里注冊你的Service
<service
android:name=".packnameName.youServiceName"
android:enabled="true" />
廣播(Broadcast Receiver)的兩種動態(tài)注冊和靜態(tài)注冊有什么區(qū)別再愈?
- 靜態(tài)注冊:在AndroidManifest.xml文件中進行注冊,當App退出后护戳,Receiver仍然可以接收到廣播并且進行相應的處理翎冲。
- 動態(tài)注冊:在代碼中動態(tài)注冊,當App退出后媳荒,也就沒辦法在接受廣播了抗悍。
保證Service不被殺死的幾種方法
1.Service設置成START_STICKY
- kill后會被重啟(等待5秒左右),重傳Intent肺樟,保持與重啟前一樣檐春。
2.提升Service的優(yōu)先級
在AndroidManifest.xml文件中對于intent-file可以通過android:proiority = "1000"
這個屬性設置最高優(yōu)先級,1000是最高值么伯,如果數(shù)字越小則優(yōu)先級越低疟暖,同樣適用于廣播。- 【結(jié)論】目前看來,priority這個屬性貌似只適用于Broadcast俐巴,對于Service來說無效骨望。
3.onDestroy方法里重啟Service
- Service + Broadcast 方式,就是當Service執(zhí)行onDestory()的時候欣舵,發(fā)送一個自定義的廣播擎鸠,當收到廣播的時候,重新啟動service缘圈。
- 也可以直接在onDestroy()里startService
- 【結(jié)論】當使用助手類軟件或者直接在設置里強制停止應用時劣光,App進程直接被結(jié)束,onDestroy方法都進不來糟把,還是無法徹底保證绢涡。
4.監(jiān)聽系統(tǒng)廣播判斷Service狀態(tài)
- 通過系統(tǒng)的一些廣播,比如:手機重啟遣疯、界面喚醒雄可、應用狀態(tài)改變等等監(jiān)聽并捕獲到,然后判斷我們的Service是否還存活缠犀。
- 【結(jié)論】這也能算是一種措施数苫,不過見聽多了會導致Service很混亂,不方便辨液。
5.root之后放到System/app變成系統(tǒng)級應用
6.放一個像素在前臺
如何判斷應用被強殺
在Application中定義一個Static常量虐急,賦值為-1,在Splash界面改為0室梅,如果被強殺戏仓,application重新初始化,在父類Activity判斷該常量的值亡鼠。
應用被強殺如何解決
如果在每一個Activity的onCreate里判斷是否被強殺,冗余了敷待,封裝到Activity的父類中间涵,如果被強殺,跳轉(zhuǎn)回主界面榜揖,如果沒有被強殺勾哩,執(zhí)行Activity的初始化操作,給主界面?zhèn)鬟fintent參數(shù)举哟,主界面會調(diào)用onNewIntent方法思劳,在onNewIntent跳轉(zhuǎn)到歡迎頁面,重新來一遍流程妨猩。
Asset目錄與res目錄的區(qū)別
res 目錄下面有很多文件潜叛,例如 drawable,mipmap,raw 等。res 下面除了 raw 文件不會被壓縮外,其余文件都會被壓縮威兜。同時 res目錄下的文件可以通過R 文件訪問销斟。Asset 也是用來存儲資源,但是 asset 文件內(nèi)容只能通過路徑或者 AssetManager 讀取椒舵。
Android怎么加速啟動Activity
啟動應用 :Application 的構(gòu)造方法蚂踊,onCreate 方法中不要進行耗時操作,數(shù)據(jù)預讀取(例如 init 數(shù)據(jù)) 放在異步中操作
啟動普通的Activity:A 啟動B 時不要在 A 的 onPause 中執(zhí)行耗時操作笔宿。因為 B 的 onResume 方法必須等待 A 的 onPause 執(zhí)行完成后才能運行
Android內(nèi)存優(yōu)化方法:ListView優(yōu)化犁钟,及時關(guān)閉資源,圖片緩存等等泼橘。
View和View Group的區(qū)別特纤?自定義View的過程?
Android的UI界面都是由View和ViewGroup及其派生類組合而成的侥加。其中捧存,View是所有UI組件的基類,而 ViewGroup是容納這些組件的容器担败,其本身也是從View派生出來的昔穴。View對象是Android平臺中用戶界面體現(xiàn)的基礎單位。View類是它稱為“widgets(工具)”的子類的基礎提前,它們提供了諸如文本輸入框和按鈕之類的UI對象的完整實現(xiàn)吗货。ViewGroup類同樣為其被稱為“Layouts(布局)”的子類奠定了基礎,它們提供了象流式布局狈网、表格布局以及相對布局之類的布局架構(gòu)宙搬。
-
如何自定義控件:
1.自定義屬性的聲明和獲取- 分析需要的自定義屬性
- 在res/values/attrs.xml定義聲明
- 在layout文件中進行使用
- 在View的構(gòu)造方法中進行獲取
2.測量onMeasure
3.布局onLayout(ViewGroup)
4.繪制onDraw
5.onTouchEvent
6.onInterceptTouchEvent(ViewGroup)
7.狀態(tài)的恢復與保存
Content的區(qū)別
- Activity和Service以及Application的Context是不一樣的,Activity繼承自ContextThemeWraper.其他的繼承自ContextWrapper
- 每一個Activity和Service以及Application的Context都是一個新的ContextImpl對象
- getApplication()用來獲取Application實例的,但是這個方法只有在Activity和Service中才能調(diào)用的到拓哺。那么也許在絕大多數(shù)情況下我們都是在Activity或者Service中使用Application的勇垛,但是如果在一些其它的場景,比如BroadcastReceiver中也想獲得Application的實例士鸥,這時就可以借助getApplicationContext()方法闲孤,getApplicationContext()比getApplication()方法的作用域會更廣一些,任何一個Context的實例烤礁,只要調(diào)用getApplicationContext()方法都可以拿到我們的Application對象讼积。
- Activity在創(chuàng)建的時候會new一個ContextImpl對象并在attach方法中關(guān)聯(lián)它,Application和Service也差不多脚仔。ContextWrapper的方法內(nèi)部都是轉(zhuǎn)調(diào)ContextImpl的方法
- 創(chuàng)建對話框傳入Application的Context是不可以的
- 盡管Application勤众、Activity、Service都有自己的ContextImpl鲤脏,并且每個ContextImpl都有自己的mResources成員们颜,但是由于它們的mResources成員都來自于唯一的ResourcesManager實例吕朵,所以它們看似不同的mResources其實都指向的是同一塊內(nèi)存
- Context的數(shù)量等于Activity的個數(shù) + Service的個數(shù) + 1,這個1為Application
IntentService的使用場景與特點
IntentService是Service的子類掌桩,是一個異步的边锁,會自動停止的服務,很好解決了傳統(tǒng)的Service中處理完耗時操作忘記停止并銷毀Service的問題
優(yōu)點:
- 一方面不需要自己去new Thread
- 另一方面不需要考慮在什么時候關(guān)閉該Service
onStartCommand中回調(diào)了onStart波岛,onStart中通過mServiceHandler發(fā)送消息到該handler的handleMessage中去茅坛。最后handleMessage中回調(diào)onHandleIntent(intent)。