IntentService使用及源码分析

IntentService使用及源码分析


转载请注明原博客地址: http://blog.csdn.net/gdutxiaoxu/article/details/52000680

本篇博客主要简介一下三个问题:

  1. 什么是IntentService?
  2. 怎样使用IntentService
  3. IntentSerice()源码分析

1)什么是IntentService?

我们知道Service和Activity一样是Android的四大组件之一,Service简称为后台服务,具有较高的优先级别。我们平时在Activity中直接开启Service,是运行在主线程的。如果想要执行耗时任务,我们必须自己开启线程。而IntentService是把任务放在子线程中执行的。


  • 我们先来看一下官方的解析是怎样的?

This “work queue processor” pattern is commonly used to offload tasks from an application’s main thread. The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, and stop the service as appropriate.
All requests are handled on a single worker thread – they may take as long as necessary (and will not block the application’s main loop), but only one request will be processed at a time.


简单来说主要有一下几点
1. Service是运行在子线程的;
2. 多个请求会按启动的顺序执行,但是一次只会处理一个任务;
3. 任务执行完毕以后会自动退出Service,不需要我们自己处理


2)下面我们来看一下我们要怎样使用IntentService?

其实跟普通的Service差不多

  • 1)自定义一个MyIntentService集成IntentService,重写构造方法和onHandleIntent方法,在HandleIntent里面执行我们的耗时任务等操作
public class MyIntentService extends IntentService {

    private static final String ACTION_DOWNLOAD = "com.szl.intentservicedemo.action.DOWNLOAD";
    private static final String ACTION_UPLOAD = "com.szl.intentservicedemo.action.UPLOAD ";


    private static final String EXTRA_PARAM1 = "com.szl.intentservicedemo.extra.PARAM1";
    private static final String EXTRA_PARAM2 = "com.szl.intentservicedemo.extra.PARAM2";
     public static final String TAG="tag";

    public MyIntentService() {
        super("MyIntentService");
    }

   //这里省略了若干个方法


    //处理我们启动的Service
    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            final String action = intent.getAction();
            if (ACTION_DOWNLOAD.equals(action)) {
                final String param1 = intent.getStringExtra(EXTRA_PARAM1);
                final String param2 = intent.getStringExtra(EXTRA_PARAM2);
                handleDOwnload(param1, param2);
            } else if (ACTION_UPLOAD.equals(action)) {
                final String param1 = intent.getStringExtra(EXTRA_PARAM1);
                final String param2 = intent.getStringExtra(EXTRA_PARAM2);
                handleUpload(param1, param2);
            }
        }
    }


}
  • 2)别忘了在清单文件里面注册我们的Service
 <service
  android:name=".MyIntentService"
  android:exported="false">
 </service>
  • 3)启动我们的Service,这里使用context.startService(intent)启动,当然你也可以用bindService启动
Intent intent = new Intent(context, MyIntentService.class);
intent.setAction(ACTION_UPLOAD);
intent.putExtra(EXTRA_PARAM1, param1);
intent.putExtra(EXTRA_PARAM2, param2);
context.startService(intent);

测试代码如下

public void onButtonClick(View view) {
    switch (view.getId()) {
        case R.id.btn_download:
            MyIntentService.startActionDownLoad(MainActivity.this, "下载", "发起者主线程");
            break;

        case R.id.btn_upload:
            MyIntentService.startActionUpload(MainActivity.this, "上传", "发起者主线程");
            break;

        default:
            break;
    }
}

运行以上测试程序,依次点击模拟上传和模拟下载,将可在我们的控制台上看到以下的log信息

控制台输出的Log


IntentService源码分析

这里先贴出IntentService的源码

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);
        }
    }

    /**
     * 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;
    }

    /**
     * Sets intent redelivery preferences.  Usually called from the constructor
     * with your preferred semantics.
     *
     * <p>If enabled is true,
     * {@link #onStartCommand(Intent, int, int)} will return
     * {@link Service#START_REDELIVER_INTENT}, so if this process dies before
     * {@link #onHandleIntent(Intent)} returns, the process will be restarted
     * and the intent redelivered.  If multiple Intents have been sent, only
     * the most recent one is guaranteed to be redelivered.
     *
     * <p>If enabled is false (the default),
     * {@link #onStartCommand(Intent, int, int)} will return
     * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent
     * dies along with it.
     */
    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @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);
    }

    @Override
    public void onStart(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(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

    /**
     * Unless you provide binding for your service, you don't need to implement this
     * method, because the default implementation returns null. 
     * @see android.app.Service#onBind
     */
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * This method is invoked on the worker thread with a request to process.
     * Only one Intent is processed at a time, but the processing happens on a
     * worker thread that runs independently from other application logic.
     * So, if this code takes a long time, it will hold up other requests to
     * the same IntentService, but it will not hold up anything else.
     * When all requests have been handled, the IntentService stops itself,
     * so you should not call {@link #stopSelf}.
     *
     * @param intent The value passed to {@link
     *               android.content.Context#startService(Intent)}.
     */
    @WorkerThread
    protected abstract void onHandleIntent(Intent intent);
}

源码分析

分析之前我们先来看一下Service生命周期

这里我们以startService()为例分析,从我们启动一个IntentService,调用的过程大概是这样的,

构造方法 ->onCreate()- >onStartCommand()- >onStart()->Service running–>

  • 1)首先我们先来看一下构造方法里面做了什么事情
public IntentService(String name) {
    super();
    mName = name;
}

其实很简单,只是调用父类的构造方法,并保存我们的那么字段

  • 2)接着我们来看我们的onCreate方法做了什么?
@Override
public void onCreate() {
    super.onCreate();
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();

    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
}

简单来说,就是为我们初始化一个线程thread并启动它,并将线程的looper与我们的mServiceHandler绑定在一起。

  • 3)接着我们来看onStartCommand()方法做了什么?
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

我们可以看到在onStartCommand转调了onStart()方法

  • 4)onStart()方法
@Override
public void onStart(Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

在onStart()方法里面其实就是用我们的mServiceHandler发送信息(mServiceHandler.sendMessage(msg);),这样在我们handleMessage()里面讲可以收到我们的信息,在handleMessage()里面有调用onHandleIntent()去处理我们的Intent,这就是为什么我们需要重写onHandleIntent的原因。

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);
    }
}
  • 5)至于上面提到的我们的handleIntent是运行在子线程的,其实也很容易理解,因为我们知道handle运行在主线程还是子线程,是取决于我们与那个线程的looper绑定在一个的,而IntentService在onCreate方法中将我们的mServiceHandler与子线程的looper绑定在一起。核心代码体现如下
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
  • 6)为什么多个请求会按启动的顺序执行,但是一次只会处理一个任务?
    我们知道多次调用context.startService方法,不会多次调用我们的onCreate()方法,但会调用我们的onStart()方法,而在我们的onStart()方法里面我们调用mServiceHandler.sendMessage(msg);相当于是向消息队列里面插入一条信息,Looper会不断地从里面取出消息,交给相应 的hanlder处理,直到没有消息为止。如果对Handler消息机制不了解的话,建议先去了解
  • 7)为什么任务执行完毕以后会自动退出Service,不需要我们自己处理?
    这个就很简单了,因为在处理完信息以后,会调用stopSelf去停止相应的服务。
public void handleMessage(Message msg) {
    onHandleIntent((Intent)msg.obj);
    stopSelf(msg.arg1);
}

到此IntentService源码分析位置

关于HandlerThread的分析,可以查看我的 这一篇博客 :HandlerThread源码分析

转载请注明原博客地址: http://blog.csdn.net/gdutxiaoxu/article/details/52000680

例子源码下载地址: http://download.csdn.net/detail/gdutxiaoxu/9583047

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gdutxiaoxu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值