Android面試(一)

weixin_33728268發表於2018-03-13

1.Activity

四大元件之一,通常一個使用者互動介面對應一個activity。activity是Context的子類,同時實現了window.callback和keyevent.callback,可以處理與窗體使用者互動的事件。

1.1生命週期
6859758-fabd0c78e9a32196.png
image.png

onCreate:當Activity第一次啟動呼叫
onDestory:當Activity銷燬的時候呼叫
onStart:當Activity變成可見呼叫
onStop:當Activity不可見呼叫
onResume:當Activity可以互動呼叫這個方法 當介面上的按鈕被點選的時候呼叫
onPause:當Activity不可以互動呼叫這個方法 當介面上的按鈕不可以點選
onRestart:當介面重新啟動的時候呼叫
Activity建立呼叫的順序是:onCreate ---> onStart ---> onResume ---> onPause ---> onStop ---> onDestory
還有一個onRestart,其中onRestart是在Acitivity被onStop後,但是沒有被onDestory,在再次啟動此Activity時呼叫的(而不再呼叫onCreate)方法;如果被onDestory了,則是呼叫onCreate方法。
幾種情況:

  1.點選Home鍵回到主介面(Activity不可見):onPause ---> onStop
  2,當我們再次回到原Activity時: onRestart ---> onStart ---> onResume
  onRestart:已經啟動的activity,又從桌面回到activity時,再次啟動
  3.退出當前Activity時: onPause ---> onStop ---> onDestory
1.2Activity的四種狀態:running / paused / stopped / killed

1.runnig:使用者可以點選,activity處於棧頂狀態。
2.paused:activity失去焦點的時候,被一個非全屏的activity佔據或者被一個透明的activity覆蓋,這個狀態的activity並沒有銷燬,它所有的狀態資訊和成員變數仍然存在,只是不能夠被點選。(除了記憶體緊張的情況,這個activity有可能被回收)
3.stopped:這個activity被另外一個activity完全覆蓋,但是這個activity的所有狀態資訊和成員變數仍然存在(除了記憶體緊張)
4.killed:這個activity已經被銷燬,其所有的狀態資訊和成員變數已經不存在了。

1.3Android程式優先順序:前臺 / 可見 / 服務 / 後臺 / 空
  1. 前臺程式:Foreground process
    使用者正在互動的Activity(onResume())
    當某個Service繫結正在互動的Activity
    被主動呼叫為前臺Service(startForeground())
    元件正在執行生命週期的回撥(onCreate()、onStart()、onDestory())
    BroadcastReceiver正在執行onReceive()
  2. 可見程式:Visible process
    我們的Activity處在onPause()(沒有進入onStop())
    繫結到前臺Activity的Service
  3. 服務程式:Service process
    簡單的startService()啟動。
  4. 後臺程式:Background process
    對使用者沒有直接影響的程式 --- Activity處於onStop()的時候。
    android:process=":xxx"
  5. 空程式:Empty process
    不含有任何的活動的元件。(Android設計的,處於快取的目的,為了第二次啟動更快,採取的一個權衡)
1.4兩個Activity之間跳轉必然會執行的是哪幾個方法:

1、一般情況比如說有兩個activity,分別叫A、B ,當在A裡面啟用B元件的時候,A 會呼叫 onPause()方法,然後B 呼叫onCreate、onStart、 OnResume,這個時候B覆蓋了窗體,A會呼叫onStop方法. 。
2、如果B是個透明的介面,或者是對話方塊的樣式,,就不會呼叫onStop方法。

1.5 橫豎屏切換的生命週期變化:

這個生命週期跟清單檔案裡的配置有關係:
1、不設定Activity的android:configChanges時,切屏會銷燬當前Activity,然後重新載入,重新呼叫各個生命週期。onPause ---> onStop ---> onDestory ---> onCreate --->onStart ---> onResume。
2、設定Activity的android:configChanges="orientation|keyboardHidden|screenSize"時,切屏不會重新呼叫各個生命週期,只會執行 onConfigurationChanged 方法。

1.6 Activity的四種啟動模式:

清單檔案中可以配置每個activity的啟動模式,例如:
android:launchMode="standard"
(1) standard 標準模式:
特點:此模式不管有沒有已存在的例項,都生成新的例項。每次呼叫startActivity()啟動Activity時都會建立一個新的Activity放在棧頂,每次返回都會銷燬例項並出棧,可以重複建立。
(2) singleTop 單一頂部模式:
特點:會檢查任務棧棧頂的Activity,如果發現棧頂已經存在例項,就不會建立新的例項,直接複用。但如果不在棧頂,那麼還是會建立新的例項。
應用場景:瀏覽器書籤的頁面,流氓的網站,避免建立過多的書籤頁面
(3) singleTask 單一任務模式:
特點:這種模式不會檢查任務棧的棧頂,檢查當前任務棧,如果發現有例項存在,直接複用。任務棧中只有一個例項儲存(把當前activity上面的所有的其它activity都清空,複用這個已經存在的activity)
應用場景:瀏覽器瀏覽頁面的Activity,播放器播放的activity。
(4) singleinstance 單一例項模式
特點:系統會為這個Activity單獨建立一個任務棧,這個任務棧裡面只有一個例項存在並且保證不再有其它activity例項進入。
應用場景:來電頁面。

1.7scheme跳轉協議:

Android中的scheme是一種頁面內跳轉協議,是一種非常好的實現機制,通過定義自己的scheme協議,可以非常方便跳轉app中的各個頁面;通過scheme協議,伺服器可以定製化告訴app跳轉哪個頁面,可以通過通知欄訊息定製化跳轉頁面,可以通過H5頁面跳轉頁面等。

關於scheme跳轉協議,可以檢視下面的部落格,站在巨人的肩膀上,才能看得更遠
Android產品研發(十一)-->應用內跳轉Scheme協議

1.8 如果後臺的activity由於某原因被系統回收了,如何在被系統回收之前儲存當前狀態:

除了在棧頂的activity,其他的activity都有可能在記憶體不足的時候被系統回收,一個activity越處於棧底,被回收的可能性就越大。
一般來說,呼叫 onPause()和 onStop()方法後的 activity 例項仍然存在於記憶體中,activity 的所有資訊和狀態資料不會消失,當 activity 重新回到前臺之後,所有的改變都會得到保留。但是當系統記憶體不足時, 呼叫onPause()和onStop()方法後的 activity可能會被系統摧毀,,此時記憶體中就不會存有該 activity 的例項物件了。如果之後這個 activity 重新回到前臺,之前所作的改變就會消失。
為了避免此種情況,我們可以覆寫onSaveInstanceState()方法。onSaveInstanceState()方法接受一個 Bundle 型別的引數,開發者可以將狀態資料儲存到這個 Bundle 物件中,這樣即使 activity 被系統摧毀,當使用者重新啟動這個 activity 而呼叫它的onCreate()方法時,上述的 Bundle 物件會作為實參傳遞給 onCreate()方法,開發者可以從 Bundle 物件中取出儲存的資料,然後利用這些資料將 activity 恢復到被摧毀之前的狀態。

但是有些情況用上面這種方式是解決不了的,比如說我們正在播放一個視訊,結果手機突然沒電了,我們想在手機充電之後,還能返回到我們之前播放的位置,就可以仿照WPS等軟體的儲存機制,可以在播放視訊的時候,每隔一段時間儲存當前進度到一個檔案中(不能是記憶體),這樣即使沒電了,但是我們之前的某個時間有儲存當前進度,所以仍然能夠回到之前播放的位置。

2.Fragment

Fragment,俗稱碎片,自Android 3.0開始被引進並大量使用。作為Activity介面的一部分,Fragment的存在必須依附於Activity,並且與Activity一樣,擁有自己的生命週期,同時處理使用者的互動動作。同一個Activity可以有一個或多個Fragment作為介面內容,並且可以動態新增、刪除Fragment,靈活控制UI內容,也可以用來解決部分螢幕適配問題。


6859758-fc8cb58b88eccbdd.png
image.png

從上圖可以看到Fragment比Activity多了幾個額外的生命週期回撥方法:


6859758-b02599bc765d557f.png
image.png
2.1 Fragment與Activity之間是如何傳值的:
  1. Activity向Fragment傳值:
    步驟:
    要傳的值,放到bundle物件裡;
    在Activity中建立該Fragment的物件fragment,通過呼叫
    fragment.setArguments()傳遞到fragment中;
    在該Fragment中通過呼叫getArguments()得到bundle物件,就能得到裡面的值。
  2. Fragment向Activity傳值:
    第一種:
    在Activity中呼叫getFragmentManager()得到fragmentManager,,呼叫findFragmentByTag(tag)或者通過findFragmentById(id)
    FragmentManager fragmentManager = getFragmentManager();
    Fragment fragment = fragmentManager.findFragmentByTag(tag);
    第二種:
    通過回撥的方式,定義一個介面(可以在Fragment類中定義),介面中有一個空的方法,在fragment中需要的時候呼叫介面的方法,值可以作為引數放在這個方法中,然後讓Activity實現這個介面,必然會重寫這個方法,這樣值就傳到了Activity中
2. 2Fragment與Fragment之間是如何傳值的:

第一種:
通過findFragmentByTag得到另一個的Fragment的物件,這樣就可以呼叫另一個的方法了。
第二種:
通過介面回撥的方式。
第三種:
通過setArguments,getArguments的方式。

2.3FragmentTransaction的add和replace的區別:

1.add + hide + show的方式:
其實add是一層層新增上去的,通過show去顯示當前介面,hide去隱藏其他的介面,這時候的FrameLayout是會有很多層的。Fragment A 切換到Fragment B,然後再由Fragment B 切換到Fragment A 的時候,Fragment A 的所有生命週期是不會走的,只會呼叫onHiddenChanged(boolean isHidden),也就是說hide和show只是把其他介面隱藏,當前介面顯示的效果,並不會走生命週期方法。
2.replace的方式:
其實replace是會替換掉原有的,所以這種方式的FrameLayout是隻有一層的,再如上面的方式切換fragment,Fragment A會依次走生命週期方法:onAttach ---> onViewCreated ---> onActivityCreated ---> onStart。但是如果新增程式碼 ft.addToBackStack(null),生命週期方法onAttach方法就不會走。

2.4Fragment如何實現類似Activity的壓棧和出棧效果的:

Fragment的事物管理器內部維持了一個雙向連結串列結構,該結構可以記錄我們add或者replace的Fragment,然後當我們按返回鍵的時候,會自動幫我們實現出棧操作。
2.5 FragmentPagerAdapter與FragmentStatePagerAdapter的區別:
一. 由於FragmentStatePagerAdapter在destoryItem的時候呼叫mCurTransaction.remove(fragment),會回收記憶體的,而頁面比較多的時候,就比較消耗記憶體,所以FragmentStatePagerAdapter適合於頁面比較多的情況。
二. FragmentPagerAdapter在destoryItem的時候呼叫mCurTransaction.detach(fragment),沒有回收記憶體,只是將fragment與activity的UI進行分離,所以FragmentPagerAdapter適合於頁面比較少的情況。

相關文章