標籤:intentservice service
這個面試的時候,相信是面試官最愛的問題之一。簡單的來說,IntentService繼承至Service,Service和Acitivity一樣是依附於應用主進程的,它本身不是一個進程或者一個線程。一些耗時的操作可能會引起ANR的bug,(本文測試的時候,Service執行20秒沒有報ANR),而IntentService,看它的原始碼,onCreate()其實是建立了一個新的線程。
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.app;import android.content.Intent;import android.os.Handler;import android.os.HandlerThread;import android.os.IBinder;import android.os.Looper;import android.os.Message;public abstract class IntentService extends Service { private volatile Looper mServiceLooper; private volatile ServiceHandler mServiceHandler; private String mName; private boolean mRedelivery; private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); } } public IntentService(String name) { super(); mName = name; } public void setIntentRedelivery(boolean enabled) { mRedelivery = enabled; } @Override public void onCreate() { super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public void onStart(Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); } @Override public int onStartCommand(Intent intent, int flags, int startId) { onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; } @Override public void onDestroy() { mServiceLooper.quit(); } @Override public IBinder onBind(Intent intent) { return null; } protected abstract void onHandleIntent(Intent intent);}
Looper對象會每次從MessageQueue中擷取Intent對象,然後Handler處理訊息,調用void onHandleIntent(Intent intent),在這裡可以執行一些耗時的比如下載檔案等操作。每次調用IntentService都會產生新的HandlerThread,所以不會阻塞UI主線程。如果需要在一個Service裡執行耗時操作,那麼IntentService是一個很好的選擇,不用在Service裡面new Thread()或者New AsyncTask()了那麼麻煩了。下面再看看我們本實驗的demo,對比Service和IntentService對Acitivity的影響。
第一步:建立Service和IntentService
package com.figo.study.service;import android.app.Service;import android.content.Intent;import android.os.IBinder;public class TestService extends Service {@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn null;}@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {try {Thread.sleep(20000);System.out.print("service執行完成");} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return super.onStartCommand(intent, flags, startId);}}
/** * */package com.figo.study.service;import android.app.IntentService;import android.content.Intent;/** * @author Administrator * */public class TestIntentService extends IntentService {//public TestIntentService(String name) {//// TODO Auto-generated constructor stub//super(name);//}public TestIntentService() {super("TestIntentService");}/* (non-Javadoc) * @see android.app.IntentService#onHandleIntent(android.content.Intent) */@Overrideprotected void onHandleIntent(Intent intent) {// TODO Auto-generated method stubtry {Thread.sleep(20000);System.out.print("intentService執行完成");} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
第二步:AndroidManifest.xml註冊Service和Activity
<service android:name="com.figo.study.service.TestService" android:exported="false" > <intent-filter> <action android:name="TestService" /> </intent-filter> </service> <service android:name="com.figo.study.service.TestIntentService" android:exported="false" > <intent-filter> <action android:name="TestIntentService" /> </intent-filter> </service> <activity android:name="com.figo.study.IntentServiceActivity" android:theme="@android:style/Theme.NoTitleBar" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
第三步:建立測試Activity
/** * */package com.figo.study;import com.figo.study.service.TestIntentService;import com.figo.study.service.TestService;import android.app.Activity;import android.app.IntentService;import android.content.Intent;import android.os.Bundle;/** * @author figo * */public class IntentServiceActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);try {setContentView(R.layout.activity_intentservice);// 啟動一個20秒逾時的Service,因為是依附在主線程,可以看到必須等service執行完成之後,頁面才會展示出來// Intent service=new Intent("TestService");//Intent service = new Intent(IntentServiceActivity.this,//TestService.class);//startService(service);// 啟動一個20秒逾時的IntentService,因為是建立線程,所以頁面立刻就展示出來了// Intent intentService=new Intent("TestIntentService"); Intent intentService=new Intent(IntentServiceActivity.this,TestIntentService.class); startService(intentService);} catch (Exception e) {e.printStackTrace();}}}
android開發步步為營之60:IntentService與Service的區別