IntentService是handlerThread与Service的结合,因为实质是串行的执行,所以该service不适合执行频繁的网络请求类型的操作,但是他是一个用完自动停止的service,并且减轻主线程looper的压力,所以非常 适合做一些非及时性的耗时操作,如后台数据统计等.
用法
创建一个intentService,模拟一个耗时操作,发送一个广播到ui
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
/**
* 这是子线程,不需要再开一个线程了
*
* @param intent
*/
@Override
protected void onHandleIntent(Intent intent) {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//创建Intent
Intent intent1 = new Intent();
intent1.setAction("myintentService.reciver");
intent1.putExtra("string", i + "次刷新");
//发送广播
sendBroadcast(intent1);
}
}
}
ui开启服务,接受广播
public class MainActivity extends AppCompatActivity {
private TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = findViewById(R.id.tv);
MyReciver myReciver = new MyReciver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("myintentService.reciver");
registerReceiver(myReciver, intentFilter);
Intent intent = new Intent(this, MyIntentService.class);
startService(intent);
}
private class MyReciver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String string = intent.getStringExtra("string");
MainActivity.this.text.setText(string);
}
}
}
用完之后该service就停止了,当多次启动会多次执行onHandleIntent,因为原理是handler,looper来实现的,所以是串行,启动之后实则是发送一个消息.
源码
intentService的源码很简单,只有一百多行代码
public IntentService(String name) {
super();
mName = name;
}
先看构造函数,这里穿了一个线程的名字
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
再看onCreat()方法,在这里呢创建了一个handlerThread线程,并且开始执行,然后获取该线程的looper,然后赋值给handler,handler的执行型线程取决与该looper的线程,
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
再看这个onStart方法,这里启动的时候默认发送了一个消息,将intent复制给msg
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);
}
}
再看这个handler做了什么,handler接受到消息的时候调用onHandleIntent去执行,然后调用stopSelf去停止服务
public final void stopSelf(int startId) {
if (mActivityManager == null) {
return;
}
try {
mActivityManager.stopServiceToken(
new ComponentName(this, mClassName), mToken, startId);
} catch (RemoteException ex) {
}
}
再看stopSelf,该方法通过stopServiceToken停止掉了service,但是service没有被马上杀死,所以就形成了一个串行的执行,这里的startId是AMS为starService创建的一个id号,默认是递增的一个数,所以每次startService的时候都会+1,也可以认为是启动的次数,每次handler执行完消息的时候都会调用一次stopSelf,stopSelf的本身其实是根据startId来关闭服务的,只有startId是最后一起启动时候的startId才会去停掉,这也就解释了为什么多次启动IntentService会多次执行handlerIntent
@Override
public void onDestroy() {
mServiceLooper.quit();
}
mServiceLooper.quit(),该方法是将队列中的所有消息移除,并且停止循环