Android Service 詳解三:從類Service派生service
從類Service派生
如你在上節所見,使用類IntentService使得你實現一個"開始的"service非常容易.然而,如果你需要你的service以多線程方式執行(而不是使用工作隊列),那么你需要從類Service派生來處理每個intent.
相比之下,下面的例子從類Service派生并實現了與上面使用IntentService例子完全相同的工作.也就是在一個線程中序列化的處理每個"開始"請求.
public class HelloService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// 處理從線程收到的消息們
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// 通常我們在這里做一些工作比如下載一個文件
// 在我們的例子中,僅僅是睡5秒鐘.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
// 使用startId停止服務,從而使我們不會在處理
// 另一個工作的中間停止service
stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
// 啟動運行service的線程.注意我創建了一個
// 分離的線程,因為service通常都是在進程的
// 主線程中運行,但我們不想讓主線程阻塞.我們還把新線程
// 搞成后臺級的優先級,從而減少對UI線程(主線程的影響).
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// 對于每個開始請求,發送一消息來開始一次工作,并且把
// start ID也傳過去,所以當完成一個工作時,我們才知道要停止哪個請求.
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// 如果我們在這里返回后被被殺死了,重啟之.
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
@Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}
</pre> 如你所見,要做的工作比使用IntentService時多一些.</span>
然而,因為你自己處理每次對onStartCommand()的調用,你可以同時執行多個請求.這個例子并沒有那樣做,但是如果那是你所需要的,那么你可以為每個請求創建一個新的線程并且立即運行它們(而不是等待上一個請求完成).
注意方法onStartCommand()必須返回一個整數.這個整數描述了在系統殺死它的事件中系統如何繼續這個服務(如前面所述,IntentService的默認實現為你處理這些,當然你也能夠去改寫它).onStartCommand()也返回值必須是下面常量之一:
-
START_NOT_STICKY
如果系統在onStartCommand()返回后殺死了服務,不要重新創建這個service,除非還有掛起的intent需要被傳送.這是避免在不必要時運行你的service和當你的應用可以簡單重啟任何未竟的工作時的最佳選擇.
</li> -
START_STICKY
如果系統在onStartCommand()返回后殺死了這個service,會重新創建這個service并且調用onStartCommand(),但是不再重新發送上次最后一個intent,而是使用一個nullintent調用onStartCommand(),除非有一些掛起的intent,在此情況下,這些掛起的intent被派送.這適合于媒體播放器(or或相似也的服務),它不執行命令,但是無限期的運行并等待一個工作.
</li> -
START_REDELIVER_INTENT
如果系統在onStartCommand()返回后殺死了service,重新創建這個service并且使用上次最后一個intent調用onStartCommand().任何掛起的intent都順序地被派送.這適合于活躍地執行一個工作并且應被立即恢復的服務,比如下載一個文件
</li> </ul> 轉自:http://blog.csdn.net/nkmnkm/article/details/7322200