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(),該方法是將隊列中的所有消息移除,並且停止循環