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