项目地址:项目地址包含之前的内容
- 类介绍
- 使用示例
- 源码浅析
- 总结
类介绍
public abstract class IntentService extends Service {
...
protected abstract void onHandleIntent(@Nullable Intent intent);
...
}
首先IntentService是一个继承自Service的抽象类,一个抽象方法onHandleIntent,用来处理具体任务。
注释中介绍:它会根据客户端通过startService(Intent intent)发起的请求,开启工作线程,依次处理。会调用onHandleIntent抽象方法,并传入参数。处理具体的任务。
使用示例
前面介绍过Service的使用。IntentService有些大同小异而已。
- MyIntentService
public class MyIntentService extends IntentService {
protected String TAG=getClass().getSimpleName()+"----";
public MyIntentService() {
this(null);
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public MyIntentService(String name) {
super(name);
}
@Override
public void onCreate() {
super.onCreate();
Log.i("life",TAG+"onCreate--threadName: "+Thread.currentThread().getName());
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i("life",TAG+"onStart--threadName: "+Thread.currentThread().getName());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("life",TAG+"onStartCommand--threadName: "+Thread.currentThread().getName());
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i("life",TAG+"onDestroy--threadName: "+Thread.currentThread().getName());
}
@Override
public IBinder onBind(Intent intent) {
Log.i("life",TAG+"onBind--threadName: "+Thread.currentThread().getName());
return super.onBind(intent);
}
@Override
public boolean onUnbind(Intent intent) {
Log.i("life",TAG+"onUnbind--threadName: "+Thread.currentThread().getName());
return super.onUnbind(intent);
}
@Override
protected void onHandleIntent(Intent intent) {
try {
//休眠2秒钟
Thread.sleep(1000*2);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i("life",TAG+"onHandleIntent--threadName: "+Thread.currentThread().getName());
}
}
这里log了生命周期,有助于方法调用的理解。其中onHandleIntent方法中休眠了2秒钟。
2. Activity中
//创建intent和ServiceConnection
private Intent intent;
private ServiceConnection conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_service);
ButterKnife.bind(this);
intent=new Intent(this, MyIntentService.class);
conn=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
}
//点击事件
@OnClick({R.id.start, R.id.stop, R.id.bindService, R.id.unbindService})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.start:
startService(intent);
break;
case R.id.stop:
stopService(intent);
break;
case R.id.bindService:
bindService(intent,conn,Context.BIND_AUTO_CREATE);
break;
case R.id.unbindService:
unbindService(conn);
break;
default:
}
}
连续点击startService之后的log。
可以看出,Service只有一个线程,每次任务完成后在进行下次任务,知道所有任务完成,在onDestroy自己。
如果想得到任务的返回结果就需要绑定了。这里就不在累述了。
源码浅析
通过生命周期的顺序来看
- 构造方法
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public IntentService(String name) {
super();
mName = name;
}
需要传入一个名字,用来给线程命名。
2. onCreate
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
这里直接实例化了一个HandlerThread,并设置了名字。然后提供了一个Handler对象。等下再看ServiceHandler代码。
3. onStartCommand
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
/**
* You should not override this method for your IntentService. Instead,
* override {@link #onHandleIntent}, which the system calls when the IntentService
* receives a start request.
* @see android.app.Service#onStartCommand
*/
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
onStartCommand的方法和Service的不同之处是调用了一个onStart方法。而onStart方法发送了一个Message。而且方法也提示了,我们不需要在重写这个方法,而应该重写onHandleIntent方法。因为消息发出后,会自动的调用onHandleIntent。 mRedelivery 稍后再看
- ServiceHandler
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);
}
}
收到消息后获得intent调用onHandleIntent方法,之后调用stopSelf。也就是说IntentService的内部实现靠的是HandlerThread。
- setIntentRedelivery
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
如果此参数为true,onStartCommand将返回START_REDELIVER_INTENT ,否则返回START_NOT_STICKY。
START_REDELIVER_INTENT :如果onHandleIntent还没有执行完成,进程就被杀死了,进程将会被重启,并且携带会原来的Intent。如果有多任务的话,自会保留最后一个Intent。
START_NOT_STICKY:进程不会被重启,Intent也一起销毁。
总结
- IntentService利用HandlerThread,对我提供一个在子线程中执行的方法onHandleIntent
- 耗时任务完成后,会调用stopSelf,来结束自己。
- 如果绑定了IntentService,startService之后,destroy自己。
public final void stopForeground(@StopForegroundFlags int flags) {
try {
mActivityManager.setServiceForeground(
new ComponentName(this, mClassName), mToken, 0, null, flags);
} catch (RemoteException ex) {
}
}
mActivityManager是IActivityManager的对象,看不到源码。估计和mToken有关,mToken是一个IBinder对象。