天天看點

《Android移動應用開發》 複習題(一)

《Android移動應用開發》

  大家好,我是亓官劼(qí guān jié )

由于學習工作的需要,算法刷題将會逐漸由C++向Python3過度,正在過度中,如實作的不太優美,請見諒。

本文原創為【亓官劼】(qí guān jié ),請大家支援原創,部分平台一直在惡意盜取部落客的文章!!! 全部文章請關注微信公衆号【亓官劼】。

複習題(一)

(一)Android的體系結構是怎樣的?請簡要加以說明。

Android的系統架構采用了分層架構的思想,從上層到底層共包括四層,分别是應用層、應用架構層、系統運作庫層以及Linux核心層。

應用層:Android平台不僅僅是作業系統,也包含了許多應用程式,譬如SMS短信用戶端程式、電話撥号程式、圖檔浏覽器、Web浏覽器等應用。這些應用程式都是用Java語言編寫的,并且可以被開發人員開發的其他應用程式所替換。

應用架構層:該層是Android應用開發的基礎。應用架構層包括活動管理器、視窗管理器、内容提供者、視圖系統、包管理器、電話管理器、資料總管、位置管理器、通知管理器和XMPP服務十個部分。

系統運作庫層:系統運作庫層可以分成兩部分,分别是系統庫和Android運作時。

Linux核心層:Android的核心系統服務依賴于Linux核心,如安全性、記憶體管理、程序管理、網絡協定棧和驅動模型。Linux核心也同時作為硬體和軟體棧之間的抽象層。

(二)Android程式結構是怎樣的?請簡要加以分析。

解答:如以工程名稱Firstdemo作為根目錄,将所有自動生成的和非自動生成的檔案都儲存在這個根目錄下。

(1)src目錄:src目錄下是java源代碼存放目錄,裡面一般都是.java結尾的java檔案。

(2)gen目錄:gen目錄是Android開發工具自動生成的檔案。目錄中有個可自定義的包,包裡有兩個檔案,BuildConfig.java和R.java。BuildConfig.java是Android調試用的。R.java是在建立項目時自動生成的,這個檔案是隻讀模式,不能更改。

(3)res目錄:res目錄是資源目錄,可以存放應用使用到的各種資源,如XML界面檔案、圖檔、資料等。

(4)assets目錄:assets資源目錄一般可用于存放html檔案、資料庫檔案、javascript檔案等,還有原始格式的檔案,例如二進制格式的音頻檔案、視訊檔案等。

(5)AndroidMamifest.xml

AndroidMamifest.xml項目清單檔案列出了應用程式提供的功能,開發好的各種元件需要在此檔案中進行配置,當應用使用到系統内置的應用(如電話服務、網際網路服務、短信服務、GPS服務等)還需在此檔案中聲明使用權限。每個Android程式必須在根目錄下包含一個AndroidMamifest.xml檔案。

(三)Activity的四種啟動模式是什麼?并請加以說明。

Standard、single Top、single Task、single Instance

Standard:預設模式,會在啟動時建立一個新執行個體,建立的模式也可以随Intent.FLAG_ACTIVITY_NEW_TASK而改變

single Top:當啟動activity時,有相同的activity在前台與使用者互動,那就複用這個activity,這個執行個體會被調用Activity.onNewIntent()。

single Task:在啟動activity時,若有一個運作着這個activity的task,那這個activity執行個體會被調到前台,并調用Activity.onNewIntent() ,啟動執行個體的Intent的flag會被設定Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT . singleTask是singleTop的一個擴充集。

single Instance:開辟一個隻允許一個activity執行個體在裡頭運作的task. 如果用同樣的intent再次啟動這個activity,task會被調到前台,其Activity.onNewIntent() 會被調用. 如果這個activity執行個體要啟動一個新activity,那麼這個新activity會在一個新task中運作.

(四)Handler消息傳遞機制是怎樣的?舉例加以說明。

利用Handler消息傳遞的過程是:使用Handler發送消息,該消息被傳送到指定的Message Queue。為了保證正常工作,目前線程必須有Message Queue,而Message Queue 是由Looper 對象來管理的。是以要求目前線程必須有一個Looper對象,根據不同類型的線程,處理情況不同,主要分為以下兩類:

主線程:系統以及為其初始化了Looper對象,是以可以直接建立Handler對象,并由該Handler對象發送,處理消息。

非主線程:先調用Looper的prepare()方法建立一個Looper對象,然後調用Looper的loop()方法啟動它。

當線程有了Looper對象之後,再建立Handler子類的執行個體,重寫handleMessage()方法處理消息,最後由loop()啟動Looper對象。

(五)如何發送廣播?如何接收系統廣播消息?

Android廣播分為兩個方面:廣播發送者和廣播接收者。通常情況下,BroadcastReceiver指的就是廣播接收者(廣播接收器),用于異步接收廣播Intent。廣播Intent是通過調用Context.sendBroadcast()發送、BroadcastReceiver()接收。廣播Intent的發送是通過調用Context.sendBroadcast()、Context.sendOrderedBroadcast()、Context.sendStickyBroadcast()來實作的。通常一個廣播Intent可以被訂閱了此Intent的多個廣播接收者所接收。

廣播接收器隻能接收廣播,對廣播的通知做出反應,很多廣播都産生于系統代碼,如:時區改變的通知、電池電量不足、使用者改變了語言偏好,或者開機啟動等。

廣播接收器沒有使用者界面,但是它可以為它們接收到資訊啟動一個Activity或者使用NotificationManager來通知使用者。

解答:Android系統中内置了多個系統廣播,隻要涉及到手機的基本操作,基本上都會發出相應的系統廣播。如:開機啟動,網絡狀态改變,拍照,螢幕關閉與開啟,點亮不足等等。每個系統廣播都具有特定的intent-filter,其中主要包括具體的action,系統廣播發出後,将被相應的BroadcastReceiver接收。系統廣播在系統内部當特定事件發生時,由系統自動發出。(程式設計實作略。)

(六)Service 和 Thread 的差別是什麼?為什麼使用Service?注意事項是什麼?

Thread是程式執行的最小單元,可以用Thread來執行一些異步操作。而Service是Android的一種機制,當它運作的時候如果是Local Service,那麼對應的Service是運作在主程序的main線程中的。如果是Remote Service,那麼對應的Service則是運作在獨立程序的main線程中。

Service可以用來處理一些比較複雜的操作,并且不會因為系統記憶體緊張而被“殺掉”。

Service不是一個單獨的程序,除非單獨聲明,否則它不會運作在單獨的程序中,而是和啟動它的程式運作在同一程序中。Service也不是線程,這意味着它将在主線程裡運作。

(七)比較程序内服務與跨程序服務的不同。

程序内服務:同一個程序下調用的服務, (通常情況下)即在一個應用程式下的服務。

跨程序服務:通過一個應用程式(用戶端)的 Activity 調用另一個應用程式(服務端)的 Service 為跨程序服務。在 Android 中,如果需要在不同程序間實作通信,就需要用到 AIDL 技術去完成。

(八)Executor、ExecutorService和Executors的差別是什麼?

Executor 是一個簡單的标準化接口,用于定義類似于線程的自定義子系統,包括線程池、異步 IO 和輕量級任務架構。根據所使用的具體 Executor 類的不同,可能在新建立的線程中,現有的任務執行線程中,或者調用 execute() 的線程中執行任務,并且可能順序或并發執行。

ExecutorService 提供了多個完整的異步任務執行架構。 ExecutorService 管理任務的排隊和安排, 并允許受控制的關閉。

Executors 類提供大多數 Executor 的常見類型和配置的工廠方法, 以及使用它們的幾種實用工具方法

Java 裡面線程池的頂級接口是 Executor ,但是嚴格意義上講 Executor 并不是一個線程池,而隻是一個執行線程的工具。真正的線程池接口是 ExecutorService 。ExecutorService 繼承Executor 。Executors 類為建立 ExecutorService 提供了便捷的工廠方法。

(九)ThreadPoolExecutor和ExecutorService有怎樣的關系?ThreadPoolExecutor的構造方法是怎樣的?試對ThreadPoolExecutor構造方法的參數加以說明。

關系:ThreadPoolExecutor是ExecutorSevice的一個實作類, 它使用可能的兒個池線程之一執行每個送出的任務,通常使用Executors工廠方法配置。

方法:1. 用給定的初始參數和預設的線程工廠及被拒絕的執行處理程式建立新的ThreadPoolExecutor.

2. 用給定的初始參數和預設的線程工廠建立新的ThreadpoolExecutor.

3. 用給定的初始參數和預設被拒絕的執行處理程式建立新的ThreadPoolExecutor.

4. 用給定的初始參數建立新的ThreadPoolExecutor.

說明:✧corePoolSize: 池中所儲存的線程數,包括空閑線程。

✧maximumPoolSize: 池中允許的最大線程數。

✧keepAliveTime: 當線程數大于核心時,此為終止前多餘的空閑線程等待新任務的最長時間。

✧unit: keepAliveTime 參數的時間機關。

✧workQueue;:執行前用于保持任務的隊列。此隊列僅保持由execute 方法送出的

Runnable任務。

✧threadFactory;:執行程式建立新線程時使用的工廠,

✧Handler: 由于超出線程範圍和隊列容量而使執行被阻塞時所使用的處理程式。

(十)為什麼說Executors類為建立ExecutorService提供了便捷的工廠方法?

要配置一個線程池是比較複雜的, 尤其是對于線程池的原理不是很清楚的情況下, 很有可能配置的線程池不是較優的, 是以在 Executors 類裡面提供了一些靜态工廠, 生成一些常用的線程池。

( 1) newCachedThreadPool : 建立一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,那麼就會回收部分空閑( 60 秒不執行任務)的線程,當任務數增加時,此線程池又可以智能地添加新線程來處理任務。 此線程池不會對線程池大小做限制, 線程池大小完全依賴于作業系統(或者說 JVM )能夠建立的最大線程大小。

( 2) newFixedThreadPool : 建立固定大小的線程池。每次送出一個任務就建立一個線程,直到線程達到線程池的最大大小。 線程池的大小一旦達到最大值就會保持不變, 如果某個線程因為執行異常而結束,那麼線程池會補充一個新線程。

( 3) newSingleThreadExecutor : 建立一個單線程的線程池。這個線程池隻有一個線程在工作,也就是相當于單線程串行執行所有任務。 如果這個唯一的線程因為異常結束, 那麼會有一個新的線程來替代它。此線程池保證所有任務的執行順序按照任務的送出順序執行。

( 4) newScheduledThreadPool :建立一個定長線程池, 此線程池支援定時以及周期性執行任務的需求。

(十一)Java中的強引用、軟引用、弱引用的差別是什麼?

強引用:是指建立一個對象并把這個對象指派給一一個引用變量。 強引用不為null時,它指向的對象水遠不會被垃圾回收,即使當記憶體不足時。當強引用被置為nul時,該對象則被标記為可回收的,但是GC可能依舊沒有回收它,這和GC的回收算法有關,同時該對象仍然占着記憶體。總之,我們不能保證可回收的對象被GC回收。

軟引用:通過SoftReference類來實作。軟引用指向的對象,不用置null,也可以被GC回收,對象是否被釋放取決于GC算法以及GC運作時可用的記憶體數量。通俗地講,記憶體空間足夠,GC就不會回收它;如果記憶體空間不足了,就會回收這些對象的記憶體。

弱引用:通過WeakReference類來建立。GC運作時如果碰到了弱引用對象,不管目前記憶體空間足夠與否,都會回收它的記憶體,但是也有可能需要GC多次才能發現和釋放弱引用的對象。

軟引用和弱引用都可以與引用隊列( ReferenceQueue)關聯,這樣就可以知道軟引用或者弱引用是否被回收。

(十二)什麼是觀察者模式?觀察者模式的使用場景是怎樣的?觀察者模式的優缺點是什麼?試程式設計加以說明。

觀察者模式就是定義對象間一種一對多的依賴關系,使得每當一個對象改變狀态,則所有依賴于它的對象都會得到通知并被自動更新。

使用場景:

(1)關聯行為場景。需要注意的是,關聯行為是可拆分的,而不是“組合”關系。

(2)事件多級觸發場景。

(3)跨系統的消息交換場景,如消息隊列的處理機制。

優點:觀察者和被觀察者之間是抽象耦合;建立了一套觸發機制。

缺點:開發和調試比較複雜,而且一個觀察者卡殼,會影響整體的執行效率。同時多級觸發時的效率讓人擔憂。

(十三)什麼是裝飾模式?裝飾模式的使用場景是怎樣的?裝飾模式的優缺點是什麼?試程式設計加以說明。

裝飾模式就是動态地給一個對象添加一些額外的職責。

使用場景:

(1)需要擴充一個類的功能,或給一個類增加附加功能。

(2)需要動态地給一個對象增加功能,這些功能可以再動态地撤銷。

(3)需要為一批的兄弟類進行改裝或加裝功能,當然是首選裝飾模式。

優點:

(1)裝飾類和被裝飾類可以獨立發展,而不會互相耦合。

(2)裝飾模式是繼承關系的一個替代方案。

(3)裝飾模式可以動态地擴充一個實作類的功能,這不需要多說,裝飾模式的定義就是如此。

缺點:多層類的裝飾太過複雜。

(十四)循環對象 Looper 的作用是什麼?請加以說明。

用于為一個線程開啟一個消息隊列(MessageQueue),循環等待其他線程發送消息,當有消息時會喚起線程來處理消息,直到線程結束為止。通常情況下Android中并不會為新線程開啟消息循環,不會用到Looper,而主線程除外,系統自動為主線程建立一個Looper對象,并建立消息隊列,是以主線程會一直運作, 以處理使用者事件,直至退出。

當需要一個線程時,這個線程要能夠循環處理其他線程發來的消息事件,或者需要長期與其他線程進行複雜的互動,這時就需要用到Looper來為線程建立消息隊列。

Looper對象提供了以下幾個方法:

●prepare(): 用于初始化Looper, prepare( )方法保證每個線程至多隻有一個Looper對象。

●loop(): 用于開啟消息循環,當調用了loop( )方法後,Looper線程就真正地開始工作

了,它會從消息隊列中擷取消息并交給對應的Handle對象處理消息。

●quit(): 用于結束Looper消息循環。