1.Activity
四大組件之一,通常一個用戶交互界面對應(yīng)一個activity。activity是Context的子類,同時實現(xiàn)了window.callback和keyevent.callback,可以處理與窗體用戶交互的事件。
1.1生命周期

onCreate:當(dāng)Activity第一次啟動調(diào)用
onDestory:當(dāng)Activity銷毀的時候調(diào)用
onStart:當(dāng)Activity變成可見調(diào)用
onStop:當(dāng)Activity不可見調(diào)用
onResume:當(dāng)Activity可以交互調(diào)用這個方法 當(dāng)界面上的按鈕被點擊的時候調(diào)用
onPause:當(dāng)Activity不可以交互調(diào)用這個方法 當(dāng)界面上的按鈕不可以點擊
onRestart:當(dāng)界面重新啟動的時候調(diào)用
Activity創(chuàng)建調(diào)用的順序是:onCreate ---> onStart ---> onResume ---> onPause ---> onStop ---> onDestory
還有一個onRestart,其中onRestart是在Acitivity被onStop后,但是沒有被onDestory,在再次啟動此Activity時調(diào)用的(而不再調(diào)用onCreate)方法;如果被onDestory了,則是調(diào)用onCreate方法。
幾種情況:
1.點擊Home鍵回到主界面(Activity不可見):onPause ---> onStop
2,當(dāng)我們再次回到原Activity時: onRestart ---> onStart ---> onResume
onRestart:已經(jīng)啟動的activity,又從桌面回到activity時,再次啟動
3.退出當(dāng)前Activity時: onPause ---> onStop ---> onDestory
1.2Activity的四種狀態(tài):running / paused / stopped / killed
1.runnig:用戶可以點擊,activity處于棧頂狀態(tài)。
2.paused:activity失去焦點的時候,被一個非全屏的activity占據(jù)或者被一個透明的activity覆蓋,這個狀態(tài)的activity并沒有銷毀,它所有的狀態(tài)信息和成員變量仍然存在,只是不能夠被點擊。(除了內(nèi)存緊張的情況,這個activity有可能被回收)
3.stopped:這個activity被另外一個activity完全覆蓋,但是這個activity的所有狀態(tài)信息和成員變量仍然存在(除了內(nèi)存緊張)
4.killed:這個activity已經(jīng)被銷毀,其所有的狀態(tài)信息和成員變量已經(jīng)不存在了。
1.3Android進程優(yōu)先級:前臺 / 可見 / 服務(wù) / 后臺 / 空
- 前臺進程:Foreground process
用戶正在交互的Activity(onResume())
當(dāng)某個Service綁定正在交互的Activity
被主動調(diào)用為前臺Service(startForeground())
組件正在執(zhí)行生命周期的回調(diào)(onCreate()、onStart()、onDestory())
BroadcastReceiver正在執(zhí)行onReceive() - 可見進程:Visible process
我們的Activity處在onPause()(沒有進入onStop())
綁定到前臺Activity的Service - 服務(wù)進程:Service process
簡單的startService()啟動。 - 后臺進程:Background process
對用戶沒有直接影響的進程 --- Activity處于onStop()的時候。
android:process=":xxx" - 空進程:Empty process
不含有任何的活動的組件。(Android設(shè)計的,處于緩存的目的,為了第二次啟動更快,采取的一個權(quán)衡)
1.4兩個Activity之間跳轉(zhuǎn)必然會執(zhí)行的是哪幾個方法:
1、一般情況比如說有兩個activity,分別叫A、B ,當(dāng)在A里面激活B組件的時候,A 會調(diào)用 onPause()方法,然后B 調(diào)用onCreate、onStart、 OnResume,這個時候B覆蓋了窗體,A會調(diào)用onStop方法. 。
2、如果B是個透明的界面,或者是對話框的樣式,,就不會調(diào)用onStop方法。
1.5 橫豎屏切換的生命周期變化:
這個生命周期跟清單文件里的配置有關(guān)系:
1、不設(shè)置Activity的android:configChanges時,切屏?xí)N毀當(dāng)前Activity,然后重新加載,重新調(diào)用各個生命周期。onPause ---> onStop ---> onDestory ---> onCreate --->onStart ---> onResume。
2、設(shè)置Activity的android:configChanges="orientation|keyboardHidden|screenSize"時,切屏不會重新調(diào)用各個生命周期,只會執(zhí)行 onConfigurationChanged 方法。
1.6 Activity的四種啟動模式:
清單文件中可以配置每個activity的啟動模式,例如:
android:launchMode="standard"
(1) standard 標(biāo)準(zhǔn)模式:
特點:此模式不管有沒有已存在的實例,都生成新的實例。每次調(diào)用startActivity()啟動Activity時都會創(chuàng)建一個新的Activity放在棧頂,每次返回都會銷毀實例并出棧,可以重復(fù)創(chuàng)建。
(2) singleTop 單一頂部模式:
特點:會檢查任務(wù)棧棧頂?shù)腁ctivity,如果發(fā)現(xiàn)棧頂已經(jīng)存在實例,就不會創(chuàng)建新的實例,直接復(fù)用。但如果不在棧頂,那么還是會創(chuàng)建新的實例。
應(yīng)用場景:瀏覽器書簽的頁面,流氓的網(wǎng)站,避免創(chuàng)建過多的書簽頁面
(3) singleTask 單一任務(wù)模式:
特點:這種模式不會檢查任務(wù)棧的棧頂,檢查當(dāng)前任務(wù)棧,如果發(fā)現(xiàn)有實例存在,直接復(fù)用。任務(wù)棧中只有一個實例存儲(把當(dāng)前activity上面的所有的其它activity都清空,復(fù)用這個已經(jīng)存在的activity)
應(yīng)用場景:瀏覽器瀏覽頁面的Activity,播放器播放的activity。
(4) singleinstance 單一實例模式
特點:系統(tǒng)會為這個Activity單獨創(chuàng)建一個任務(wù)棧,這個任務(wù)棧里面只有一個實例存在并且保證不再有其它activity實例進入。
應(yīng)用場景:來電頁面。
1.7scheme跳轉(zhuǎn)協(xié)議:
Android中的scheme是一種頁面內(nèi)跳轉(zhuǎn)協(xié)議,是一種非常好的實現(xiàn)機制,通過定義自己的scheme協(xié)議,可以非常方便跳轉(zhuǎn)app中的各個頁面;通過scheme協(xié)議,服務(wù)器可以定制化告訴app跳轉(zhuǎn)哪個頁面,可以通過通知欄消息定制化跳轉(zhuǎn)頁面,可以通過H5頁面跳轉(zhuǎn)頁面等。
關(guān)于scheme跳轉(zhuǎn)協(xié)議,可以查看下面的博客,站在巨人的肩膀上,才能看得更遠(yuǎn)
Android產(chǎn)品研發(fā)(十一)-->應(yīng)用內(nèi)跳轉(zhuǎn)Scheme協(xié)議
1.8 如果后臺的activity由于某原因被系統(tǒng)回收了,如何在被系統(tǒng)回收之前保存當(dāng)前狀態(tài):
除了在棧頂?shù)腶ctivity,其他的activity都有可能在內(nèi)存不足的時候被系統(tǒng)回收,一個activity越處于棧底,被回收的可能性就越大。
一般來說,調(diào)用 onPause()和 onStop()方法后的 activity 實例仍然存在于內(nèi)存中,activity 的所有信息和狀態(tài)數(shù)據(jù)不會消失,當(dāng) activity 重新回到前臺之后,所有的改變都會得到保留。但是當(dāng)系統(tǒng)內(nèi)存不足時, 調(diào)用onPause()和onStop()方法后的 activity可能會被系統(tǒng)摧毀,,此時內(nèi)存中就不會存有該 activity 的實例對象了。如果之后這個 activity 重新回到前臺,之前所作的改變就會消失。
為了避免此種情況,我們可以覆寫onSaveInstanceState()方法。onSaveInstanceState()方法接受一個 Bundle 類型的參數(shù),開發(fā)者可以將狀態(tài)數(shù)據(jù)存儲到這個 Bundle 對象中,這樣即使 activity 被系統(tǒng)摧毀,當(dāng)用戶重新啟動這個 activity 而調(diào)用它的onCreate()方法時,上述的 Bundle 對象會作為實參傳遞給 onCreate()方法,開發(fā)者可以從 Bundle 對象中取出保存的數(shù)據(jù),然后利用這些數(shù)據(jù)將 activity 恢復(fù)到被摧毀之前的狀態(tài)。
但是有些情況用上面這種方式是解決不了的,比如說我們正在播放一個視頻,結(jié)果手機突然沒電了,我們想在手機充電之后,還能返回到我們之前播放的位置,就可以仿照WPS等軟件的保存機制,可以在播放視頻的時候,每隔一段時間保存當(dāng)前進度到一個文件中(不能是內(nèi)存),這樣即使沒電了,但是我們之前的某個時間有保存當(dāng)前進度,所以仍然能夠回到之前播放的位置。
2.Fragment
Fragment,俗稱碎片,自Android 3.0開始被引進并大量使用。作為Activity界面的一部分,F(xiàn)ragment的存在必須依附于Activity,并且與Activity一樣,擁有自己的生命周期,同時處理用戶的交互動作。同一個Activity可以有一個或多個Fragment作為界面內(nèi)容,并且可以動態(tài)添加、刪除Fragment,靈活控制UI內(nèi)容,也可以用來解決部分屏幕適配問題。

從上圖可以看到Fragment比Activity多了幾個額外的生命周期回調(diào)方法:

2.1 Fragment與Activity之間是如何傳值的:
- Activity向Fragment傳值:
步驟:
要傳的值,放到bundle對象里;
在Activity中創(chuàng)建該Fragment的對象fragment,通過調(diào)用
fragment.setArguments()傳遞到fragment中;
在該Fragment中通過調(diào)用getArguments()得到bundle對象,就能得到里面的值。 - Fragment向Activity傳值:
第一種:
在Activity中調(diào)用getFragmentManager()得到fragmentManager,,調(diào)用findFragmentByTag(tag)或者通過findFragmentById(id)
FragmentManager fragmentManager = getFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(tag);
第二種:
通過回調(diào)的方式,定義一個接口(可以在Fragment類中定義),接口中有一個空的方法,在fragment中需要的時候調(diào)用接口的方法,值可以作為參數(shù)放在這個方法中,然后讓Activity實現(xiàn)這個接口,必然會重寫這個方法,這樣值就傳到了Activity中
2. 2Fragment與Fragment之間是如何傳值的:
第一種:
通過findFragmentByTag得到另一個的Fragment的對象,這樣就可以調(diào)用另一個的方法了。
第二種:
通過接口回調(diào)的方式。
第三種:
通過setArguments,getArguments的方式。
2.3FragmentTransaction的add和replace的區(qū)別:
1.add + hide + show的方式:
其實add是一層層添加上去的,通過show去顯示當(dāng)前界面,hide去隱藏其他的界面,這時候的FrameLayout是會有很多層的。Fragment A 切換到Fragment B,然后再由Fragment B 切換到Fragment A 的時候,F(xiàn)ragment A 的所有生命周期是不會走的,只會調(diào)用onHiddenChanged(boolean isHidden),也就是說hide和show只是把其他界面隱藏,當(dāng)前界面顯示的效果,并不會走生命周期方法。
2.replace的方式:
其實replace是會替換掉原有的,所以這種方式的FrameLayout是只有一層的,再如上面的方式切換fragment,F(xiàn)ragment A會依次走生命周期方法:onAttach ---> onViewCreated ---> onActivityCreated ---> onStart。但是如果添加代碼 ft.addToBackStack(null),生命周期方法onAttach方法就不會走。
2.4Fragment如何實現(xiàn)類似Activity的壓棧和出棧效果的:
Fragment的事物管理器內(nèi)部維持了一個雙向鏈表結(jié)構(gòu),該結(jié)構(gòu)可以記錄我們add或者replace的Fragment,然后當(dāng)我們按返回鍵的時候,會自動幫我們實現(xiàn)出棧操作。
2.5 FragmentPagerAdapter與FragmentStatePagerAdapter的區(qū)別:
一. 由于FragmentStatePagerAdapter在destoryItem的時候調(diào)用mCurTransaction.remove(fragment),會回收內(nèi)存的,而頁面比較多的時候,就比較消耗內(nèi)存,所以FragmentStatePagerAdapter適合于頁面比較多的情況。
二. FragmentPagerAdapter在destoryItem的時候調(diào)用mCurTransaction.detach(fragment),沒有回收內(nèi)存,只是將fragment與activity的UI進行分離,所以FragmentPagerAdapter適合于頁面比較少的情況。