IntentService是Service的子类,他不是普通的Service,比普通的Service增加了额外功能。
Service本身存在两个问题:
Service不会专门启动一条单独的线程,Service与它所在的应用处于同一个进程中。
Service也不是一条新的线程,因此不应该在Service中直接处理耗时任务。
如果开发者需要在Service中处理耗时任务,建议在Service中另外启动一条新的线程来处理该耗时任务。直接在其他程序组件中启动子线程来处理耗时任务不行吗?这种方式不可靠,由于Activity会被用户退出,BroadcastReceiver的生命周期本身就很短,可能出现的情况是:在子线程还没有结束的情况下,Activity已经被用户退出了,或者BroadcastReceiver已经结束了。在Activity一经推出,BroadcastReceiver已经结束的情况下,此时他们所处的进程就变成了空进程。系统需要内存的时候,可能就会有优先终止该进程。如果宿主进程被终止,那么该进程内的所有子线程也会被终止,这样就导致线程无法执行该任务。
而IntentService正好可以弥补Service上述两个不足:IntentService将会使用队列来管理请求Intent,每当客户代码通过Intent请求启动IntentService的时候,IntentService会将该Intent加入队列中,然后开启一条新的worker线程来处理该Intent,该线程保证同一时刻只处理一个Intent,由于IntentService使用新的worker线程处理Intent请求,因此,IntentService不会阻塞主线程,所以,IntentService自己就可以处理耗时任务。
IntentService有如下特征:
IntentService会创建单独的worker线程来处理所有的Intent请求。
IntentService会创建单独的worker线程来处理OnHandlerIntent()方法实现代码,因此开发者无需处理多线程问题。
当所有的请求处理完成以后,IntentService会自动停止,因此开发者无需调用stopSelf()方法来停止该Service。
为Service的onbind()方法提供默认实现,默认实现的onBind()返回为null。
为service的OnStartCommand()方法提供了默认实现,该实现会请求Intent添加到队列中。
从上面的介绍可以看出,扩展IntentService实现Service无需重写onBind(),OnStartCommand()方法,只要重写onhandleIntent()方法即可。
下面是两个测试例子:
public class MyService extends Service
{
public MyService()
{
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
long endTime = System.currentTimeMillis() + 20 * 1000;
System.out.println("onStart");
while (System.currentTimeMillis() < endTime)
{
synchronized (this)
{
try
{
wait(endTime - System.currentTimeMillis());
}
catch (Exception e)
{
}
}
}
System.out.println("-----耗时任务执行完成-----");
return START_STICKY;
}
public class MyIntentService extends IntentService
{
public MyIntentService()
{
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent)
{
long endTime = System.currentTimeMillis() + 20*1000;
System.out.println("onStart");
while(System.currentTimeMillis() < endTime)
{
synchronized (this)
{
try
{
wait(endTime - System.currentTimeMillis());
}
catch (Exception e)
{
}
System.out.println("-----耗时任务执行完成-----");
}
}
}
}
测试的Activity
public class MainActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService()
{
Intent intent = new Intent(this,MyService.class);
startService(intent);
}
public void startIntentService()
{
Intent intent = new Intent(this,MyIntentService.class);
startService(intent);
}
}
运行该实例,如果启动普通的Service按钮,将会激发StartService()方法,导致UI线程被阻塞,出现ANR异常。如果调用IntentService来启动,虽然也执行耗时任务,但由于MyIntentService会使用单独的worker线程,因此,不会阻塞前台,程序不会失去响应。