这个面试的时候,相信是面试官最爱的问题之一。简单的来说,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 {
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
Thread.sleep(20000);
System.out.print("service执行完成");
} catch (Exception e) {
// TODO Auto-generated catch block
e.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)
*/
@Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
try {
Thread.sleep(20000);
System.out.print("intentService执行完成");
} catch (Exception e) {
// TODO Auto-generated catch block
e.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 {
@Override
protected 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();
}
}
}