之前介绍了Android Service与Thread的区别(点击查看Service与Thread区别),由于Service不是线程,它是在主线程中运行的,因此在Service中应该避免耗时操作,之前看到过很多帖子和代码都把耗时操作交给Service去处理,这样是不合理的。如果Service中有耗时操作一定要new 一个Thread去处理。
下面写一个错误的示例,即将耗时操作直接放在Service中进行。
//Service
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
Log.i("Test", "Service start...");
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i("Test", "Service end...");
}
}
//测试主程序
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this, MyService.class));
//...填充UI
}
}
测试结果显示Service开启后,MainActivity被阻塞住,UI界面无法绘制。等待一段时间后Activity出现假死现象,点击“等待”按钮,Service睡眠30秒后,程序正常。
因此在Service中如果进行耗时操作,正确的做法是开启一个线程。
除了在Service中开启线程之外,Android提供了IntentService来处理耗时操作。
IntentService继承自Service,但相比Service有以下优点:
使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程,这里就给我们提供了一个思路,如果有耗时的操作与其在Service里面开启新线程还不如使用IntentService来处理耗时操作。
这里给出一个IntentService处理耗时操作的例子:
public class MyIntentService extends IntentService {
public MyIntentService() {
super("Test");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.i("Test", "Service start...");
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i("Test", "Service end...");
}
}
//测试主程序
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this, MyIntentService.class));
startService(new Intent(this, MyIntentService.class));//开启两个IntentService,观察执行
//...填充UI
}
}
测试结果显示,MyIntentService开启后Activity并未阻塞,可以正常运行。两个IntentService按照先进先出的原则依次执行。
因此我们在处理Service中有耗时操作的时候,可以尝试使用IntentService代替Thread.