一、IntentService是什么
正常情况下,Service和Activity一样,都是处于主线程中,不能做耗时操作,但是IntentService却可以,IntentService是继承Service的抽象类,用于处理异步请求任务,并在任务结束后,自动销毁。正是由于IntentService是Service,优先级较高,不易被回收,因此可以用来在后台执行耗时和重要的任务。
二、IntentService使用实例
通过IntentService实现文件下载效果,效果如图所示:
例子代码如下:
1. IntentService的实现
继承IntentService,并实现onHandleIntent()方法,由于该方法是在工作线程中调用,因此可以在该方法中执行耗时操作;代码实现,如下:
public class MyIntentService extends IntentService {
private static final String TAG = "MyIntentService";
public static final String ACTION = "test.intent.service.action";
public static final String PARAM_PROGRESS = "local.broadcast.progress";
private LocalBroadcastManager mLocalBroadcastManager;
private int progress;
public MyIntentService() {
super("MyIntentService");
}
@Override
public void onCreate() {
super.onCreate();
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
Log.i(TAG, "onCreate");
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand,startId:" + startId);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy");
}
@Override
protected void onHandleIntent(Intent intent) {
progress = 0;
while (progress < 100) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
progress++;
Intent intentSend = new Intent();
intentSend.setAction(ACTION);
intentSend.putExtra(PARAM_PROGRESS, progress);
mLocalBroadcastManager.sendBroadcast(intentSend);
Log.i(TAG, "当前进度progress:" + progress);
Log.i(TAG, "当前线程onHandleIntent:" + Thread.currentThread().getName());
}
}
}
复制代码
2. 启动IntentService
Intent intent = new Intent(this, MyIntentService.class);
startService(intent);
复制代码
3. 接收回传进度,更新进度条
class LocalBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int progress = intent.getIntExtra(MyIntentService.PARAM_PROGRESS, 0);
progressbar.setProgress(progress);
Log.i(TAG, "progress:" + progress);
Log.i("TAG, "当前线程onReceive:" + Thread.currentThread().getName());
}
}
复制代码
打印结果:
三、IntentService实现原理
可以把IntentService理解为Service和HandlerThread,在IntentService的onCreate()方法中,创建了一个HandlerThread,然后获取到HandlerThread工作线程Looper对象,创建了一个该工作线程的Handler对象,代码如下:
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
复制代码
通过start方式启动的Service生命周期方法是先调用onCreate()方法,然后是onStartCommand()方法,当调用stopService()或stopSelf()方法,会调Service的onDestroy()方法;
在onStartCommand()方法中调用了onStart()方法,在onStart方法中,通过Handler发送给HandlerThread的工作线程一个消息,当handleMessage()接收到Message后,调用了onHandleIntent()来处理消息,然后执行stopSelf(startId)来结束IntentService;代码如下:
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
复制代码
四、IntentService的思考
1. IntentSercice的启动模式
Service有两种启动模式,start模式和bind模式,IntentService是Service的子类,也是有这两种启动模式的;在Service中,start模式用于没有数据交互的启动模式,有数据交互的,最好使用bind模式,IntentService是不是也是这样的呢?其实InentService不是这样的,InentService是可以执行耗时操作的Service,并在任务执行结束后,自动结束;InentService结束服务的方式是stopSelf(startId),如果使用bind方式启动,则在任务执行结束后,Service就不能停止了,这样是违背InentService设计的初衷的,因此InentService只能通过start方式启动;
2. 如何进行数据回传
由于InentService只能通过start方式启动,因此不能用bindService这种方式进行数据的传递,我们可以使用广播,EventBus,回调等方式来完成数据的交互;
3. 多次启动生命周期流程
当多次调用startService,可以看到打印结果如下:
onCreat方法执行了一次,每调用一次startService就会调用一次onStartCommand,最后执行onDestroy方法,则整个Service生命周期结束。每次调用startService传递数据时,都会调用onStartCommand中接收数据,onStartCommand把intent放到Message的obj参数中,则在handleMessage中可以收到startService传递过来的数据。
需要注意的是:由于Handler是个消息队列,所以每次调用startService的时候,只有在上一个消息执行完成之后才再次会回调onHandleIntent方法。
由于个人能力和水平有限,如有不足之处,希望大家能够给与批评和指正,希望能和大家一起学习,一起进步。