码迷,mamicode.com
首页 > 其他好文 > 详细

IntentService源码详解

时间:2014-07-08 18:50:24      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:android   des   style   blog   http   java   

IntentService可以做什么:

如果你有一个任务,分成n个子任务,需要它们按照顺序完成。如果需要放到一个服务中完成,那么IntentService就会使最好的选择。


IntentService是什么:

IntentService是一个Service(看起来像废话,但是我第一眼看到这个名字,首先注意的是Intent啊。),所以如果自定义一个IntentService的话,一定要在AndroidManifest.xml里面声明。

从上面的“可以做什么”我们大概可以猜测一下IntentService要有什么特性。

首先要明确的是,如果在Activity中启动一个Service,那么这个Service是在主线程中的。所以在IntentService中需要一个工作线程来完成Intent请求。从IntentService的定义可以印证该猜测:

IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
IntentService用来按要求处理异步请求(以Intent的方式发送的)。客户端通过调用startService(Intent)发送请求,服务会按照要求启动,用自己的工作线程(区别于UI主线程)处理每个Intent(请求),当完成所有的请求之后,自动关闭。


IntentService源码解析:

干货来了!IntentService代码包含了一个工作线程Thread、工作线程的Looper、工作线程的Handler。工作线程用来干活的,Looper用来让线程运转起来的,Handler负责向线程传送工作内容的。IntentService的源码简洁透彻的体现了这一个机制。光是看看这个机制就值了。源码如下:

路径:alps\frameworks\base\core\java\android\app\IntentService.java 

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) {
            //自定义的IntentService子类主要就是实现onHandleIntent这个函数了。注意执行完这个之后就
            //stopSelf了,传入的参数是startId。
            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();
        //好好看看下面这个代码,启动了一个工作线程,获取线程的Looper,然后用这个Looper初始化Handler句柄
        //这样以后可以直接用mHandler.sendMessage的方式将任务直接放到工作线程了。
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

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

    @Override
    public void onStart(Intent intent, int startId) {
        //从消息队列中获取一个消息,一般都是用这种方式初始化一个消息,而不是用new message()形式
        //效率更高,代码更健壮
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;//
        msg.obj = intent;//这个就是startService的时候传入的Intent了,
        mServiceHandler.sendMessage(msg);//将包含请求内容Intent的message传入到工作线程中
    }

    /**
     * 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,和它传入的值。
        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)}.
     */
    protected abstract void onHandleIntent(Intent intent);
}

从线程分析:

如果是自定义IntentService的话,可以在函数中打印Thread.currentThread().getName()将当前所在线程打印出来。就会发现,只有onHandleIntent的执行是在另外一个新线程中,其他函数(onCreate/onStart/onStartCommand等)的执行都是在main线程(主线程的名称)中。


示例代码:

实际的代码参考如下:

package com.example.fmdemo;

import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class IntentServiceDemo extends IntentService {

	private static final String TAG = "IntentServiceDemo";

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

	public IntentServiceDemo(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void onHandleIntent(Intent arg0) {
		// TODO Auto-generated method stub
		String action = arg0.getExtras().getString("param");
		if ("oper1".equals(action)) {
			Log.i(TAG, "onHandleIntent oper1 threadname = "
					+ Thread.currentThread().getName());
		} else if ("oper2".equals(action)) {
			Log.i(TAG, "onHandleIntent oper2 threadname = "
					+ Thread.currentThread().getName());
		}

		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onBind threadname = " + Thread.currentThread().getName());
		return super.onBind(intent);
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		Log.i(TAG, "onCreate threadname = " + Thread.currentThread().getName());
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		Log.i(TAG, "onDestroy threadname = " + Thread.currentThread().getName());
		super.onDestroy();
	}

	@Override
	public void onStart(Intent intent, int startId) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onStart threadname = " + Thread.currentThread().getName());
		super.onStart(intent, startId);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onStartCommand threadname = "
				+ Thread.currentThread().getName());
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void setIntentRedelivery(boolean enabled) {
		// TODO Auto-generated method stub
		Log.i(TAG, "setIntentRedelivery threadname = "
				+ Thread.currentThread().getName());
		super.setIntentRedelivery(enabled);
	}

}

在自定义的Activity的onCreate中添加如下代码:

		Intent startServiceIntent = new Intent("com.example.fmdemo.intentservice");
		Bundle bundle = new Bundle();
		bundle.putString("param", "oper1");
		startServiceIntent.putExtras(bundle);
		startService(startServiceIntent);
		
		
		Intent startServiceIntent2 = new Intent("com.example.fmdemo.intentservice");
		Bundle bundle2 = new Bundle();
		bundle2.putString("param", "oper2");
		startServiceIntent2.putExtras(bundle2);
		startService(startServiceIntent2);

运行结果如下:

07-01 06:58:23.557: I/IntentServiceDemo(3732): onCreate threadname = main
07-01 06:58:23.571: I/IntentServiceDemo(3732): onStartCommand threadname = main
07-01 06:58:23.571: I/IntentServiceDemo(3732): onStart threadname = main
07-01 06:58:23.576: I/IntentServiceDemo(3732): onHandleIntent oper1 threadname = IntentService[IntentServiceDemo]
07-01 06:58:23.577: I/IntentServiceDemo(3732): onStartCommand threadname = main
07-01 06:58:23.577: I/IntentServiceDemo(3732): onStart threadname = main
07-01 06:58:25.577: I/IntentServiceDemo(3732): onHandleIntent oper2 threadname = IntentService[IntentServiceDemo]
07-01 06:58:27.579: I/IntentServiceDemo(3732): onDestroy threadname = main

可以看到onHandleIntent是在不同main主线程的工作线程中运行的。

IntentService使用比较简单,但是实现机制比较有趣。感兴趣的同学可以自己把代码敲进去看看。


参考文章:

1. Android中IntentService的原理及使用

2. IntentService

IntentService源码详解,布布扣,bubuko.com

IntentService源码详解

标签:android   des   style   blog   http   java   

原文地址:http://blog.csdn.net/murphykwu/article/details/37502961

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!