android service 之二(IntentService)

不管是何種Service,它默認都是在應用程序的主線程(亦即UI線程)中運行的。所以,如果你的Service將要運行非常耗時或者可能被阻塞的操作時,你的應用程序將會被掛起,甚至會出現ANR錯誤。為了避免這一問題,你應該在Service中重新啟動一個新的線程來進行這些操作。現有兩種方法共大家參考:

① 直接在Service的onStartCommand()方法中重啟一個線程來執行,如:

Java代碼   收藏代碼
  1. @Override  
  2.     public int onStartCommand(Intent intent, int flags, int startId) {  
  3.         MyServiceActivity.updateLog(TAG + " ----> onStartCommand()");  
  4.         new Thread(new Runnable() {  
  5.             @Override  
  6.             public void run() {  
  7.                 // 此處進行耗時的操作,這裡只是簡單地讓線程睡眠了1s  
  8.                 try {  
  9.                     Thread.sleep(1000);  
  10.                 } catch (Exception e) {  
  11.                     e.printStackTrace();  
  12.                 }  
  13.             }  
  14.         }).start();  
  15.         return START_STICKY;  
  16.     }  

 ② Android SDK 中為我們提供了一個現成的Service類來實現這個功能,它就是IntentService,它主要負責以下幾個方面:

   

  • Creates a default worker thread that executes all intents delivered to onStartCommand() separate from your application's main thread.
  •     生成一個默認的且與主線程互相獨立的工作者線程來執行所有傳送至 onStartCommand() 方法的Intetnt

  • Creates a work queue that passes one intent at a time to your onHandleIntent() implementation, so you never have to worry about multi-threading.
  •     生成一個工作隊列來傳送Intent對象給你的onHandleIntent()方法,同一時刻只傳送一個Intent對象,這樣一來,你就不必擔心多線程的問題。

  • Stops the service after all start requests have been handled, so you never have to call stopSelf().
  •     在所有的請求(Intent)都被執行完以後會自動停止服務,所以,你不需要自己去調用stopSelf()方法來停止該服務

  • Provides default implementation of onBind() that returns null.
  •     提供了一個onBind()方法的默認實現,它返回null

  • Provides a default implementation of onStartCommand() that sends the intent to the work queue and then to your onHandleIntent() implementation
  •     提供了一個onStartCommand()方法的默認實現,它將Intent先傳送至工作隊列,然後從工作隊列中每次取出一個傳送至onHandleIntent()方法,在該方法中對Intent對相應的處理

     

    以上,英文來自官方SDK,中文為我所譯。

     

    從以上看來,你所需要做的就是實現 onHandleIntent() 方法,在該方法內實現你想進行的操作。另外,繼承IntentService時,你必須提供一個無參構造函數,且在該構造函數內,你需要調用父類的構造函數,如下:

    Java代碼   收藏代碼
    1. public HelloIntentService() {        
    2.     super("HelloIntentService");    
    3. }  

      

    下面給出一例,來解釋一下:

    Java代碼   收藏代碼
    1. // activity 的onCreate()  
    2. @Override  
    3.     public void onCreate(Bundle savedInstanceState) {  
    4.         super.onCreate(savedInstanceState);  
    5.         setContentView(R.layout.main);  
    6.   
    7.         startSer1 = (Button) findViewById(R.id.startSer1);  
    8.         stopSer1 = (Button) findViewById(R.id.stopSer1);  
    9.   
    10.         startSer2 = (Button) findViewById(R.id.startSer2);  
    11.         stopSer2 = (Button) findViewById(R.id.stopSer2);  
    12.   
    13.         log = (TextView) findViewById(R.id.log);  
    14.   
    15.         logView = (ScrollView) findViewById(R.id.logView);  
    16.   
    17.         startSer1.setOnClickListener(btnListener);  
    18.         stopSer1.setOnClickListener(btnListener);  
    19.   
    20.         startSer2.setOnClickListener(btnListener);  
    21.         stopSer2.setOnClickListener(btnListener);  
    22.   
    23.         intent = new Intent(MyServiceActivity.this, IntentServiceDemo.class);  
    24.   
    25.         // 打印出主線程的ID  
    26.         long id = Thread.currentThread().getId();  
    27.         updateLog(TAG + " ----> onCreate() in thread id: " + id);  
    28.     }  

    书籍推荐