IntentService继承Service,它包含了Service的全部特性,当然也包含service的生命周期,那么与service不同的是,IntentService在执行onCreate操作的时候,内部开了一个线程,去执行你的耗时操作。
IntentService源码:
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import static android.app.Service.START_NOT_STICKY;
import static android.app.Service.START_REDELIVER_INTENT;
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
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);
}
}
public IntentService(String name) {
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
protected abstract void onHandleIntent(Intent intent);
}
从源码中可以看出,IntentService在onCreate操作的时候,通过HandlerThread开启了一个内部线程,耗时操作可以放在onHandleIntent(Intent intent)的重载函数中。
为了便于理解,写了一个上传图片的demo。
继承于IntentService的上传图片的Service:
package com.zrp.myintentservice;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import static android.os.Build.VERSION_CODES.M;
public class UploadImgService extends IntentService
{
private static final String ACTION_UPLOAD_IMG = "com.zhy.blogcodes.intentservice.action.UPLOAD_IMAGE";
public static final String EXTRA_IMG_PATH = "com.zhy.blogcodes.intentservice.extra.IMG_PATH";
public static void startUploadImg(Context context, String path)
{
Intent intent = new Intent(context, UploadImgService.class);
intent.setAction(ACTION_UPLOAD_IMG);
intent.putExtra(EXTRA_IMG_PATH, path);
context.startService(intent);
}
public UploadImgService()
{
super("UploadImgService");
}
@Override
protected void onHandleIntent(Intent intent)
{
if (intent != null)
{
final String action = intent.getAction();
if (ACTION_UPLOAD_IMG.equals(action))
{
final String path = intent.getStringExtra(EXTRA_IMG_PATH);
handleUploadImg(path);
}
}
}
private void handleUploadImg(String path)
{
try
{
//模拟上传耗时
Thread.sleep(3000);
Intent intent = new Intent(MainActivity.UPLOAD_RESULT);
intent.putExtra(EXTRA_IMG_PATH, path);
sendBroadcast(intent);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
@Override
public void onCreate()
{
super.onCreate();
Log.e("TAG","onCreate");
}
@Override
public void onDestroy()
{
super.onDestroy();
Log.e("TAG","onDestroy");
}
}
MainAcitivity:
package com.zrp.myintentservice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
public static final String UPLOAD_RESULT = "com.zhy.blogcodes.intentservice.UPLOAD_RESULT";
private LinearLayout mLyTaskContainer;
private BroadcastReceiver uploadImgReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == UPLOAD_RESULT) {
String path = intent.getStringExtra(UploadImgService.EXTRA_IMG_PATH);
handleResult(path);
Log.d("zeng","MainActivity BroadcastReceiver Thread Name: " + Thread.currentThread().getName());
}
}
};
private void handleResult(String path) {
TextView tv = (TextView) mLyTaskContainer.findViewWithTag(path);
tv.setText(path + " upload success ~~~ ");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLyTaskContainer = (LinearLayout) findViewById(R.id.id_ll_taskcontainer);
Log.d("zeng","MainActivity Thread Name: " + Thread.currentThread().getName());
registerReceiver();
}
private void registerReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(UPLOAD_RESULT);
registerReceiver(uploadImgReceiver, filter);
}
int i = 0;
public void addTask(View view) {
//模拟路径
String path = "/sdcard/imgs/" + (++i) + ".png";
UploadImgService.startUploadImg(this, path);
TextView tv = new TextView(this);
mLyTaskContainer.addView(tv);
tv.setText(path + " is uploading ...");
tv.setTag(path);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(uploadImgReceiver);
}
}
MainActivity的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+id/id_ll_taskcontainer"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<Button android:layout_width="wrap_content" android:layout_height="wrap_content"
android:onClick="addTask" android:text="add Task"/>
</LinearLayout>
Menifest.xml中注册UploadImgService
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".UploadImgService"/>
</application>