1. 程式人生 > >Android面試系列之Android基礎知識

Android面試系列之Android基礎知識

這兩天就要換工作了,為了拿到offer,是時候來一波面試準備了!希望自己能找到心儀的工作。也希望這篇部落格能幫助到大家。

本篇部落格是相對基礎的知識,雖然是基礎,但是很重要,你能保證你都記住了麼?

Activity相關

Activity是四大元件之一,應該是我們開發中接觸最多的元件了吧。那麼問題來了!

什麼是Activity?
Activity是Android中的一個元件,提供了一個介面用於和使用者互動,使使用者可以在介面上進行點選、滑動等操作。

Activity的四種狀態
running / paused / stopped / killed

running: 表明Activity處於活動(完全可見)狀態,使用者可以與螢幕進行互動,此時,Activity處於棧頂。
paused:

表明Activity處於失去焦點的狀態(例如:被非全屏的的Activity覆蓋),此時使用者無法與該Activity進行互動。
stopped: 表明activity處於不可見的狀態(例如:被另一個Activity完全覆蓋)。
killed: 表明Activity被系統回收了,

Activity生命週期

首先來一張經典的圖:
這裡寫圖片描述

Activity生命週期大致可以分為四個場景:

1.Activity啟動–>onCreate()–>onStart()–onResume();
onCreate是Activity被建立的時候呼叫,是生命週期的第一個方法,在這裡我們可以做一些初始化操作。
onStart表明Activity正在啟動,此時處於使用者可見狀態,但是並不能與使用者互動
onResume表明Activity已經處於前臺狀態,可以與使用者互動了。

2.點選Home鍵–>onPause()–>onStop()
onPause:表明Activity處於paused狀態,此時Activity無法與使用者互動
onStop:一般在onPause後面執行,表明Activity處於完全不可見的狀態。

3.點選home後再次回到程式時–>onRestart()–>onStart()–>onResume()
onRestart:表明Activity正在重新啟動,從不可見狀態變為可見狀態

4.退出當前Activity–onPause()–>onStop()–>onDestory()
onDestory:表明Activity正在被銷燬,是整個生命週期方法中的最後一個方法,在該方法中我們可以做一些資源回收的工作。

android中的程序優先順序

前臺/可見/服務/後臺/空

前臺:包含正在處於和使用者互動的Activity或者是前臺Activity綁定了service
可見:activity處於可見狀態但不可與使用者進行互動
服務:包含一個service服務的程序
後臺:處於不可見的狀態下(比如按了home鍵)
空:沒有活躍的元件 知識為了快取的目的存在的,隨時都可能被系統殺掉

Android任務棧
用於儲存Activity,當用戶啟動Activity或者退出Activity的時候,都會在棧中做一些新增或刪除的操作。

Activity啟動模式
1.standard
預設的啟動模式,每次啟動Activity的時候都會建立一個新的例項。不會複用Activity,對記憶體消耗較大。

2.singleTop
棧頂複用模式,如果要建立的Activity已經在棧頂的話,那麼不會重新建立,直接複用,否則,仍然會重新建立。

3.singletask
棧內複用模式,如果要建立的Activity在棧內已經存在的話,不會重新建立,直接複用棧記憶體在的Activity,且會呼叫onNewIntent()方法,並且將該Activity以上的所有的Activity銷燬。

4.singleInstance
單一例項,獨享一個任務棧,整個手機作業系統裡面只有一個例項存在。用的較少。

scheme跳轉協議
android中的scheme是一種頁面內跳轉協議,通過自定義的scheme協議,可以方便的跳轉app中的各個頁面。通過scheme協議,服務端可以定製化告訴App跳轉到哪個頁面,可以通過通知欄訊息定製化跳轉頁面,也可以通過H5頁面跳轉頁面等。

Fragment相關

fragment在平時專案開發中用的也非常多,是Android3.0後引入的,起初是為了在大螢幕上更靈活的去展現ui。現在通常使用的方式是fragment+viewpager. fragment有自己的生命週期,必須依附Activity。

Fragment載入到Activity的兩種方式

1.靜態載入,在佈局中載入
2.動態載入,在程式碼中載入(用的較多)
這裡寫圖片描述

fragment經常和viewpager一起使用,不可避免的我們就會接觸到FragmentPagerAdapter和FragmentStatePagerAdapter。

FragmentPagerAdapter和FragmentStatePagerAdapter有什麼區別呢?
FragmentStatePagerAdapter在切換的時候會回收fragment
而FragmentPagerAdapter在切換時會將fragment與viewPager分離,並儲存fragment的ui資訊,
相比之下FragmentStatePagerAdapter更節省記憶體。所以在,在fragment比較多的時候推薦使用FragmentStatePagerAdapter。

Fragment的生命週期
Fragment是必須依附於Activity的,因此Activity的生命週期會直接影響到Fragment的生命週期。

這裡寫圖片描述

詳細的生命週期我們來看下面這張圖:

這裡寫圖片描述

由圖片我們可以看整個fragment和Activity的生命週期執行順序

fragment從建立到建立完成:

1.呼叫fragment中的onAttach()                fragment與Activity發生關聯時呼叫
2.呼叫fragment中的onCreate()                建立fragment時呼叫
3.呼叫fragment中的onCreateView()            繪製fragment檢視時呼叫
4.呼叫fragment中的onViewCreated()           介面繪製完成後呼叫
5.呼叫activity中的onCreate()                activity建立了
6.呼叫fragment中的onActivityCreated()       在activity的onCreate()方法之後呼叫,表明activity已經繪製完成
7.呼叫activity中的onstart()                 表明activity可見了
8.呼叫fragment中的onstart()                 activity可見後呼叫fragment中的onstart(),表明fragment也可見了
9.呼叫activity的onresume()方法               表明activity可以跟使用者互動了
10.呼叫fragment的onResume()方法              此時,fragment也可以與使用者進行互動了,到此為止,fragment完全初始化完畢了。

fragment的銷燬過程:

1.呼叫fragment中的onPause()             此時fragment不可與使用者互動
2.呼叫activity中的onPause()             此時activity不可與使用者互動
3.呼叫fragment中的onStop()              此時fragment不可見
4.呼叫activity中的onStop()              此時activity不可見
5.呼叫fragment中的onDestoryView()       fragment檢視被移除呼叫
6.呼叫fragment中的onDestory()           fragment銷燬時呼叫
7.呼叫fragment中的onDetach()            fragment與activity解除關聯時呼叫
8.呼叫activity中的ondDestory()          activity銷燬

fragment通訊

1.fragment呼叫Activity中的方法
通過getActivity()呼叫

2.在Activity中呼叫Fragment中的方法
需要在fragment類中定義一個介面並在Activity中實現它。Fragment在onAttach()回撥函式中獲取介面的具體實現的物件。然後,fragment就可以呼叫介面中的方法實現與Activity的通訊。

3.在Fragment中調Fragment中的方法
通過getSupportFragmentManager().findFragmentById()

FragmentManager中的add,remove和replace
一般我們兩種模式,一種是將fragment新增(add)到容器中,控制其隱藏和顯示。這種模式不會銷燬fragment。
另一種就是替換(replace)這種方法會把之前的fragment銷燬掉。

Service相關

service是四大元件之一,用的地方也很多。可以在後臺執行一些邏輯。

什麼是Service
Service是一種能在後臺執行耗時任務的沒有介面顯示的元件。需要注意的是Service和BroadCastReceiver都是執行在主執行緒的,所以,Service本身不能做耗時操作,而是通過子執行緒去完成!

Service和Thread的區別
詳細可以看這篇部落格service和thread的區別
講的非常仔細。

在這裡做個總結:
Thread和Service實際上是沒有任何關係,只不過因為字面上的意思,我們可能會誤解為Service可以執行耗時任務的,實際上Service是執行在主執行緒上的,也就是說,Service本身並不能做耗時操作,一般都是在Service中啟執行緒去執行耗時任務。

Thread是程式執行的最小單元,是獨立與Activity執行的,也就是說,如果我們在Activity中啟執行緒去執行任務,即使這個activity被銷燬了,該任務也會繼續執行。
而Service是Android中一種機制,在一些執行在後臺的不需要介面的地方可以使用Service。

Service的生命週期
onbind/onCreate/onStartCommand/ondestory

onBind(): 該方法返回的是一個IBinder介面,當我們使用bindService的時候才會被呼叫
onCreate(): 服務首次建立時呼叫,注意,只有service第一個被建立時才會呼叫
onStartCommand(): 每次呼叫startService的時候都會執行該方法,該方法有一個int型別的返回值
這裡寫圖片描述

分別是:START_STICKY、START_NOT_STICKY、START_REDELIVER_INTENT、START_STICKY_COMPATIBILITY。
START_STICKY:”粘性的”,如果service程序被意外kill掉,保留service的狀態為開始狀態,但不保留遞送的intent物件。隨後系統會嘗試重新建立service,由於服務狀態為開始狀態,所以建立服務後一定會呼叫onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動命令被傳遞到service,那麼引數Intent將為null。
START_NOT_STICKY:“非粘性的”。使用這個返回值時,如果在執行完onStartCommand後,服務被異常kill掉,系統不會自動重啟該服務
START_REDELIVER_INTENT:重傳Intent。使用這個返回值時,如果在執行完onStartCommand後,服務被異常kill掉,系統會自動重啟該服務,並將Intent的值傳入。
START_STICKY_COMPATIBILITY:START_STICKY的相容版本,但不保證服務被kill後一定能重啟。

onDestory(): 服務銷燬時呼叫,在這裡可以做一些資源回收操作。

Service的兩種啟動方式

startService 和 bindService

startService
1.定義一個類繼承自Service
2.在清單配置檔案中宣告
3.使用Context.startService(Intent)啟動Service
4.呼叫Context.stopService(Intent)停止Service

 Intent intent = new Intent();
 intent.setClass(activity, UpdateApkService.class);
 activity.startService(intent);//開啟服務

執行startService時,Service會經歷onCreate->onStartCommand。當執行stopService時,直接呼叫onDestroy方法。呼叫者如果沒有stopService,那麼即使Activity被銷燬了,Service也會繼續執行,下次呼叫者再起來仍然可以stopService。

bindService
1.建立一個類繼承自Service,並在類中建立一個實現IBinder介面的例項物件並提供公共方法。


    /*這裡定義一個類  用於返回Service*/
    public class MyBinder extends Binder {
        public MyService getService() {
            return MyService.this;
        }

    }
    /*提供一個公共方法*/
    public Date getTime(){
        return new Date();
    }

2.在onBind()中返回自定義的IBinder例項

  private MyBinder myBinder=new MyBinder();


    @Override
    public IBinder onBind(Intent intent) {
        return myBinder;
    }

3.在需要呼叫的地方,從onServiceConnected中獲取IBinder例項並呼叫公共方法

  sc = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.i("aaa","onServiceConnected");
                MyService.MyBinder myBinder = (MyService.MyBinder) service;
                Date date = ((MyService.MyBinder) service).getService().getTime();
                Log.i("aaa",date.toString());
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        };

        Intent intent = new Intent(this, MyService.class);
        bindService(intent, sc, BIND_AUTO_CREATE);

執行bindService時,Service會經歷onCreate->onBind。這個時候呼叫者和Service繫結在一起。呼叫者呼叫unbindService方法或者呼叫者Context不存在了(如Activity被finish了),Service就會呼叫onUnbind->onDestroy。這裡所謂的繫結在一起就是說兩者共存亡了。

BroadcastReceiver

四大元件之一,在Android中,Broadcast是一種廣泛運用在應用程式之間傳輸資訊的機制,Android中我們要傳送的是一個intent,intent可易攜帶我們需要傳輸的資料。

廣播的使用場景
1.同一app中不同元件之間的資料傳遞
2.不同app之間元件的資料傳遞

廣播的種類

1.普通廣播 Context.sendBroadcast
2.有序廣播 Context.sendOrderedBroadcast 根據優先順序傳播,優先順序高的接收器和一阻止繼續傳播活修改資料
3.本地廣播 LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); lbm.sendBroadcast(new Intent(LOCAL_ACTION)); 只會在應用內部傳播,相對來說資料安全。

廣播的註冊方式

1.靜態註冊 在清單配置檔案中宣告,即使程序被殺死,該廣播仍然執行

<receiver android:name=".MyReceiver">  
            <intent-filter>  
                <action android:name="android.intent.action.MY_BROADCAST"/>  
                <category android:name="android.intent.category.DEFAULT" />  
            </intent-filter>  
        </receiver>  

2.動態註冊 在程式碼中註冊,受activity生命週期的影響。

MyReceiver receiver = new MyReceiver();  

IntentFilter filter = new IntentFilter();  
filter.addAction("android.intent.action.MY_BROADCAST");  

registerReceiver(receiver, filter);  

內部實現機制
1.自定義BroadcastReceiver,重寫onReceive()方法
2.通過Binder機制向AMS(Activity Manager Service)進行註冊
3.廣播發送者通過Binder機制向AMS傳送廣播
4.AMS查詢符合相應條件(IntentFilter/Permission等)的BroadcastReceiver,將廣播發送到BroadCastReceiver相應的訊息迴圈佇列中
5.訊息迴圈執行拿到廣播,回撥BroadCastReceiver中的onReceive()方法。

LocalBroadcastManager
1.使用LocalBroadcastManager傳送的廣播只能在app內部傳播,因此資料傳輸很安全。
2.比系統廣播更加高效,底層是通過Handler傳送message實現的。