編輯:關於Android編程
剛開始使用Service
的時候,常常會有一個誤區:認為這個Service
運行於應用中一個單獨的線程。其實Service
組件和其他組件一樣,都是運行於這個應用的主線程當中的,它們都運行於同一個單一的線程。
可以把Service
簡單的理解成一個沒有界面顯示的Activity
(這個比喻其實並不准確,因為Service
可以直接調用WindowManager
實現界面展示,不過這裡暫時就這樣理解吧)。
如果需要Service
進行一個需要持續的、耗時的任務,還是需要給它開啟一個工作線程。
既然Service
進行耗時工作也要開啟的單獨的線程,那麼為什麼不讓Activity
代替Service
的工作呢?例如從網絡下載一個文件,可以讓應用對應的Activity
開啟一個下載線程單獨進行下載工作。即使用戶在下載的時候想使用其他應用也沒有關系,點擊HOME
按鈕就可以了。下載文件的那個Activity
會自動隱藏起來,根本不會影響到其他應用的使用。
這看上去也是可以的,不過千萬不能忽略了安卓系統的回收機制。假如系統資源需要回收,操作系統有可能把隱藏起來的Activity
給回收了,所以將一個需要長期運行的任務與隨時可能被清除的Activity
關聯在一起是很危險的。所以安卓系統引入了Service
組件來處理這種情況。Service
組件的重要性在系統當中僅次於“正在與用戶交互的Actvity”,是最不可能被系統自動回收的組件。以此來保證長期運行的任務能夠始終運行著。
很多時候,啟動一個Service
就是要它完成一個復雜而耗時的任務,完成之後,這個Service
就可以退出了。
例如文件下載。Activity
界面啟動負責下載的Service
,Service
安靜的下載,下載完成了,就可以自己退出。下載的過程中,Activity
可以繼續顯示下載的進度,也可以不用關心當前的狀態而完全退出。
Android SDK為開發者准備好了這樣一個現成的Service
-IntentService
。
IntentService
是Service
的子類,就是為了上面的那種使用場景而設計的。Android SDK對Service
類進行了進一步的封裝和擴展,方便開發者直接使用,而不需要重新造輪子了。
使用IntentService
,
繼承IntentService
,實現它的onHandlerIntent()
函數。onHandlerIntent()
是在工作線程中被調用的,所以可以在它當中添加耗時的任務處理,
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//添加耗時的任務處理
//如果intent攜帶參數,可以從intent中獲取參數
......
}
}
在AndroidManifest.xml
文件中,聲明這個Service
;
使用它的時候,直接啟動Service
就可以了。
Intent intent=new Intent(this,MyIntentService.class);
//如果需要傳遞參數,可以將參數放到intent當中
startService(intent);
使用IntentService
有幾個需要注意的地方,
Intent
發布,如果需要使用參數,參數可以通過Intent
傳遞; 一旦任務執行完成,Service
就退出了; 可以處理多個Intent
請求,但是會按照請求的先來後到挨個處理,一個接一個完成後,如果沒有任務了,Service
就退出;
和所有別的應用組件一樣,Service
需要在AndroidManifest.xml
文件中聲明。
在應用的AndroidManifest.xml
文件中,要給Service
設置上android:exported
屬性,
android:exported
屬性設置成true
:可被其他應用使用; android:exported
屬性設置成false
:只能被自己所在的應用使用;
在對其他應用開放Service
的時候,也可以設置上訪問權限,只對部分應用開放使用的權限。
在AndroidManifest.xml
文件中,對要設置權限的Service
設置上android:permission
屬性,該屬性值可以任意指定一個字符串。通常使用程序的包名作為其中的一部分,這樣可以避免和其他應用中的權限聲明沖突。例如"com.anddle.serviceaccess
,
在AndroidManifest.xml
文件中,與同級的位置,對外聲明前面使用的標簽,表示這個應用發布了一個叫做com.anddle.serviceaccess
的權限,
其中android:name
屬性的值,就是
標簽中設置的android:permission
的值。
假如應用B要使用應用A中帶權限的Service
,需要在應用B的AndroidManifest.xml
中加入權限的使用,
其中,
標簽中設置的android:name
的值,就是應用A中對外聲明的那個service
的權限值。
用ADB工具啟動已知Service,
$ ./adb shell am startservice -n 包名/包名.activity名稱
這裡的包名就形如:com.android.xxx,例如
$ ./adb shell am start -n com.android.xxx/com.android.xxx.MyService
安卓系統當中也自帶了不少的Service
,比如WindowManager
BluetoothManager
等等等等。
要使用它們也很簡單,比如,
//獲取WindowManager
WindowManager windowmanager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
windowmanager.xxx();
//獲取BluetoothManager
BluetoothManager bluetoothmanager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothmanager.xxx();
獲取到這些Service
對外提供的接口以後,就可以使用這些接口了。
類似的Service還有很多很多,
在上篇文章給大家介紹深入淺析Android Fragment(上篇),包括一些基本的用法和各種API,如果還想深入學習請繼續關注本篇文章。本篇將介紹上篇提到的:如何管理F
特點:改變的是對象的實際屬性 不僅可以應用於View, 有getter和setter方法的都可以在xml中定義放在res\animator中如:animator_alph
主要思想:將一個view設計成多層:背景層,含中獎信息等;遮蓋層,用於刮獎,使用關聯一個Bitmap的Canvas在該Bitmap上,使用它的canvas.drawPat
產品要做簽到功能,簽到功能要基於一個日歷來進行,所以就根據 要求自定義了一個日歷自定義控件相信做android都知道:(1)首先創建一個類,繼承一個容器類或者是一個控件&