源码解析Android知识Android开发

IntentService使用及源码分析

2016-08-02  本文已影响198人  程序员徐公

IntentService使用及源码分析


**转载请注明原博客地址:
**

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

  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差不多

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


}
 <service
  android:name=".MyIntentService"
  android:exported="false">
 </service>
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-->

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

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

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

我们可以看到在onStartCommand转调了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);
    }
}

mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
public void handleMessage(Message msg) {
    onHandleIntent((Intent)msg.obj);
    stopSelf(msg.arg1);
}

到此IntentService源码分析位置

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

**转载请注明原博客地址: **

**例子源码下载地址: **

上一篇下一篇

猜你喜欢

热点阅读