編輯:關於Android編程
上一篇面試總結,主要講了Activity 和Intent ,這篇主要講剩下的四大組件,面試中基礎較多的就是四大組件,需要了解的知識點也很多。上一篇文章 Android 面試題總結之Android 基礎(一)
Service 是否在 main thread 中執行, service 裡面是否 能執行耗時的操作?
默認情況,如果沒有顯示的指 servic 所運行的進程, Service 和 activity 是運 行在當前 app 所在進程的 main thread(UI 主線程)裡面。
service 裡面不能執行耗時的操作(網絡請求,拷貝數據庫,大文件 )
特殊情況 ,可以在清單文件配置 service 執行所在的進程 ,讓 service 在另 外的進程中執行
Activity 怎麼和 Service 綁定,怎麼在 Activity 中啟動自 己對應的 Service?
Activity 通過 bindService(Intent service, ServiceConnection conn, int flags)跟 Service 進行綁定,當綁定成功的時候 Service 會將代理對象通過回調 的形式傳給 conn,這樣我們就拿到了 Service 提供的服務代理對象。
在 Activity 中可以通過 startService 和 bindService 方法啟動 Service。一 般情況下如果想獲取 Service 的服務對象那麼肯定需要通過 bindService()方 法,比如音樂播放器,第三方支付等。如果僅僅只是為了開啟一個後台任務那麼 可以使用 startService()方法。
Service 的生命周期
Service 有綁定模式和非綁定模式,以及這兩種模式的混合使用方式。不同 的使用方法生命周期方法也不同。
非綁定模式:當第一次調用 startService 的時候執行的方法依次為 onCreate()、onStartCommand(),當 Service 關閉的時候調用 onDestory 方 法。
綁定模式:第一次 bindService()的時候,執行的方法為 onCreate()、 onBind()解除綁定的時候會執行 onUnbind()、onDestory()。
上面的兩種生命周期是在相對單純的模式下的情形。我們在開發的過程中還 必須注意 Service 實例只會有一個,也就是說如果當前要啟動的 Service 已經存 在了那麼就不會再次創建該 Service 當然也不會調用 onCreate()方法。
一個 Service 可以被多個客戶進行綁定,只有所有的綁定對象都執行了
onBind()方法後該 Service 才會銷毀,不過如果有一個客戶執行了 onStart() 方法,那麼這個時候如果所有的 bind 客戶都執行了 unBind()該 Service 也不會 銷毀。
Service 的生命周期圖如下所示,幫助大家記憶。
什麼是 IntentService?有何優點?
我們通常只會使用 Service,可能 IntentService 對大部分同學來說都是第 一次聽說。那麼看了下面的介紹相信你就不再陌生了。如果你還是不了解那麼在 面試的時候你就坦誠說沒用過或者不了解等。並不是所有的問題都需要回答上來的。
一、IntentService 簡介
IntentService 是 Service 的子類,比普通的 Service 增加了額外的功能。
先看 Service 本身存在兩個問題:
Service 不會專門啟動一條單獨的進程,Service 與它所在應用位於同一個進
程中;
Service 也不是專門一條新線程,因此不應該在 Service 中直接處理耗時的
任務;
二、IntentService 特征
會創建獨立的 wZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcmtlciDP37PMwLS0psDty/nT0LXEIEludGVudCDH68fzOzxiciAvPg0Ku+G0tL2otsDBorXEIHdvcmtlciDP37PMwLS0psDtIG9uSGFuZGxlSW50ZW50KCm3vbeoyrXP1rXEtPrC6yzO3tDoPGJyIC8+DQq0psDttuDP37PMzsrM4js8YnIgLz4NCsv509DH68fztKbA7c3qs8m68yxJbnRlbnRTZXJ2aWNlILvh19S2r82j1rkszt7Q6LX308Mgc3RvcFNlbGYoKbe9t6g8YnIgLz4NCs2j1rkgU2VydmljZTs8YnIgLz4NCs6qIFNlcnZpY2UgtcQgb25CaW5kKCnM4bmpxKzIz8q1z9Yst7W72CBudWxsOzxiciAvPg0KzqogU2VydmljZSC1xCBvblN0YXJ0Q29tbWFuZCDM4bmpxKzIz8q1z9YsvavH68fzIEludGVudCDM7bzTtb2208HQPGJyIC8+DQrW0Ds8YnIgLz4NCsq508MgSW50ZW50U2VydmljZTxiciAvPg0Ksb7Iy9C0wcvSu7j2IEludGVudFNlcnZpY2UgtcTKudPDwP3X07mpss6/vKGjuMPA/dfT1tDSu7j2PGJyIC8+DQpNYWluQWN0aXZpdHkg0ru49iBNeUludGVudFNlcnZpY2Us1eLBvbj2wOC2vMrHy8S089fpvP61sci70OjSqtTax+W1pSDOxLz+1tDXorLhoaPV4sDv1ru4+LP2usvQxLT6wus6PC9wPg0KPHByZSBjbGFzcz0="brush:java;">
MainActivity.java:
public void click(View view){
Intent intent = new Intent(this, MyIntentService.class); intent.putExtra("start", "MyIntentService"); startService(intent);
}
MyIntentService.java
public class MyIntentService extends IntentService { private String ex = "";
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) { Toast.makeText(MyIntentService.this, "-e " + ex,
Toast.LENGTH_LONG).show(); }
};
public MyIntentService(){ super("MyIntentService");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) { ex = intent.getStringExtra("start");
return super.onStartCommand(intent, flags, startId);
}
@Override
protected void onHandleIntent(Intent intent) { /**
* 模擬執行耗時任務
* 該方法是在子線程中執行的,因此需要用到 handler 跟主線程進行通信 */
try { Thread.sleep(1000);
} catch (InterruptedException e) { e.printStackTrace();
} mHandler.sendEmptyMessage(0); try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
說說 Activity、Intent、Service 是什麼關系
他們都是 Android 開發中使用頻率最高的類。其中 Activity 和 Service 都是 Android 四大組件之一。他倆都是 Context 類的子類 ContextWrapper 的子類, 因此他倆可以算是兄弟關系吧。不過兄弟倆各有各自的本領,Activity 負責用戶 界面的顯示和交互,Service 負責後台任務的處理。Activity 和 Service 之間可 以通過 Intent 傳遞數據,因此可以把 Intent 看作是通信使者。
Service 和 Activity 在同一個線程嗎
對於同一 app 來說默認情況下是在同一個線程中的,main Thread (UI Thread)。
Service 裡面可以彈吐司麼
可以的。彈吐司有個條件就是得有一個 Context 上下文,而 Service 本身就是 Context 的子類,因此在 Service 裡面彈吐司是完全可以的。比如我們在 Service 中完成下載任務後可以彈一個吐司通知用戶。
什麼是 Service 以及描述下它的生命周期。Service 有哪 些啟動方法,有什麼區別,怎樣停用 Service?
在 Service 的生命周期中,被回調的方法比 Activity 少一些,只有 onCreate, onStart, onDestroy,
onBind 和 onUnbind。
通常有兩種方式啟動一個 Service,他們對 Service 生命周期的影響是不一樣的。
在 service 的生命周期方法 onstartConmand()可不 可以執行網絡操作?如何在 service 中執行網絡操作?
可以直接在 Service 中執行網絡操作,在 onStartCommand()方法中可以執行網絡操作
BroadcastReceiver 簡介
BroadCastReceiver 是 Android 四大組件之一,主要用於接收系統或者 app 發 送的廣播事件。
廣播分兩種:有序廣播和無序廣播。
內部通信實現機制:通過 Android 系統的 Binder 機制實現通信。 無序廣播:完全異步,邏輯上可以被任何廣播接收者接收到。優點是效率較高。 缺點是一個接收者不能將處理結果傳遞給下一個接收者,並無法終止廣播 intent 的傳播。 有序廣播:按照被接收者的優先級順序,在被接收者中依次傳播。比如有三個廣 播接收者 A,B,C,優先級是 A > B > C。那這個消息先傳給 A,再傳給 B,最 後傳給 C。每個接收者有權終止廣播,比如 B 終止廣播,C 就無法接收到。此外 A 接收到廣播後可以對結果對象進行操作,當廣播傳給 B 時,B 可以從結果對象
中取得 A 存入的數據。
在通過 Context.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, initialCode, initialData, initialExtras)時我們可以 指定 resultReceiver 廣播接收者,這個接收者我們可以認為是最終接收者,通 常情況下如果比他優先級更高的接收者如果沒有終止廣播,那麼他的 onReceive 會被執行兩次,第一次是正常的按照優先級順序執行,第二次是作為最終接收者 接收。如果比他優先級高的接收者終止了廣播,那麼他依然能接收到廣播。 在我們的項目中經常使用廣播接收者接收系統通知,比如開機啟動、sd 掛載、 低電量、外播電話、鎖屏等。 如果我們做的是播放器,那麼監聽到用戶鎖屏後我們應該將我們的播放之暫停 等。
在 manifest 和代碼中如何注冊和使用 BroadcastReceiver
在清單文件中注冊廣播接收者稱為靜態注冊,在代碼中注冊稱為動態注冊。 靜態注冊的廣播接收者只要 app 在系統中運行則一直可以接收到廣播消息,動 態注冊的廣播接收者當注冊的 Activity 或者 Service 銷毀了那麼就接收不到廣播 了。
靜態注冊:在清單文件中進行如下配置
">
動態注冊:在代碼中進行如下注冊
IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(CALL_ACTION); context.registerReceiver(receiver, intentFilter);
BroadCastReceiver 的生命周期
a. 廣播接收者的生命周期非常短暫的,在接收到廣播的時候創建, onReceive()方法結束之後銷毀;
b. 廣播接收者中不要做一些耗時的工作,否則會彈出 Application No Response 錯誤對話框;
c. 最好也不要在廣播接收者中創建子線程做耗時的工作,因為廣播接收者被 銷毀後進程就成為了空進程,很容易被系統殺掉;
d. 耗時的較長的工作最好放在服務中完成;
Android 引入廣播機制的用意
a. 從 MVC 的角度考慮(應用程序內) 其實回答這個問題的時候還可以這樣問,
android 為什麼要有那 4 大組件,現在的移動開發模型基本上也是照搬的 web 那一套 MVC 架構,只不過是改了點嫁妝而已。android 的四大組件本 質上就是為了實現移動或者說嵌入式設備上的 MVC 架構,它們之間有時候 是一種相互依存的關系,有時候又是一種補充關系,引入廣播機制可以方便 幾大組件的信息和數據交互。
b. 程序間互通消息(例如在自己的應用程序內監聽系統來電)
c. 效率上(參考 UDP 的廣播協議在局域網的方便性)
d. 設計模式上(反轉控制的一種應用,類似監聽者模式)
ContentProvider 是如何實現數據共享的
在 Android 中如果想將自己應用的數據(一般多為數據庫中的數據)提供 給第三發應用,那麼我們只能通過 ContentProvider 來實現了。
ContentProvider 是應用程序之間共享數據的接口。使用的時候首先自定義 一個類繼承 ContentProvider,然後覆寫 query、insert、update、delete 等 方法。因為其是四大組件之一因此必須在 AndroidManifest 文件中進行注冊。
把自己的數據通過 uri 的形式共享出去
android 系統下 不同程序 數據默認是不能共享訪問 需要去實現一個類去繼承 ContentProvider
public class PersonContentProvider extends ContentProvider{ public boolean onCreate(){
} query(Uri, String[], String, String[], String)
insert(Uri, ContentValues)
update(Uri, ContentValues, String, String[]) delete(Uri, String, String[])
}
第三方可以通過 ContentResolver 來訪問該 Provider。
Android 的數據存儲方式
a. File 存儲
b. SharedPreference 存儲
c. ContentProvider 存儲
d. SQLiteDataBase 存儲
e. 網絡存儲
為什麼要用 ContentProvider?它和 sql 的實現上有什麼差別?
ContentProvider 屏蔽了數據存儲的細節,內部實現對用戶完全透明,用戶只 需要關心操作數據的 uri 就可以了,ContentProvider 可以實現不同 app 之間 共享。
Sql 也有增刪改查的方法,但是 sql 只能查詢本應用下的數據庫。而 ContentProvider 還可以去增刪改查本地文件. xml 文件的讀取等。
說 說 ContentProvider 、 ContentResolver 、 ContentObserver 之間的關系
a. ContentProvider 內容提供者,用於對外提供數據
b. ContentResolver.notifyChange(uri)發出消息
c. ContentResolver 內容解析者,用於獲取內容提供者提供的數據
d. ContentObserver 內容監聽器,可以監聽數據的改變狀態
e. ContentResolver.registerContentObserver()監聽消息。
1. 前言:在平時的開發中,我們在顯示圖片是有時候需要顯示圓角圖片,我們應該都知道圓角顯示肯定是更加耗費內存和性能,會導致圖片的過度繪制等問題。但是有時候產品的設計就是這
華為手機也可以刷刷消費啦!作為國內率先商用、支持NFC+指紋支付、以用戶體驗和支付安全為核心的Huawei Pay,擁有四重保障,芯片級安全;無需聯網,無需
ListView在android開放中用的比較多,所以接下來就進行ListView的使用的講解。 首先創建一個android項目,項目名為ListViewTest. Li
因為公司需要接入Google的應用內支付(即Google的in-app Billing V3),接入過程中查閱了很多的文章,也遇到很多的問題。故此想和大家分享及交流一下心