IntentService的使用

最近自己正在实现APP中的下载模块,上网查了下基本上就是有两种方式实现:

1.多线程:自己开启另一个线程来进行下载处理(可以直接使用Handler:不推荐使用、Thread类以及AsynTask等方式的线程实现)

2.服务:开启一个下载的Service来专门进行下载操作

当然上面两种凡是实现都是没有问题的,也能达到下载的功能实现。可总觉得都各有不好的地方。

首先,线程的方式,因为线程的生命周期主要依赖于它所在的进程,当用户的当前应用经常处于后台模式时就很可能被系统回收从而导致

下载线程也被杀死,下载可能没有完成,毕竟一般的下载任务都是比较长的。当然你也可以使用preference或数据库记录下载的地址、进度等内容再实现断点续传。可是总是

感觉比较麻烦。

再说那个服务的方式,当然一些比较正规的大公司的APP一般使用Service的方式比较多。可能他们更加的重视用户的用户体验和数据功能的

完整性。毕竟服务进程被杀死的可能性低得多,这样比较能保障用户下载的数据能够完成。当然这种方式我个人也比较倾向,你看腾讯之类的公司

的APP中总是有很多后台Service。但是我觉得下载这个任务应该属于短暂性的后台任务,如果非有个后台常驻服务总是让你很不爽。

所以在我决定使用Service方式的时候,看到Service几种启动命令时有段注释引起我的兴趣

For applications targeting Android 1.5 or beyond, you may want consider using the android.app.IntentService class, which takes care of all the work of creating the extra thread and dispatching commands to it.
所以我就看了下IntentService的源代码:不是很长 就贴出来了

package android.app;

import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;

/**
 * IntentService is a base class for {@link Service}s that handle asynchronous
 * requests (expressed as {@link Intent}s) on demand.  Clients send requests
 * through {@link android.content.Context#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.
 *
 * <p>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 {@link #onHandleIntent(Intent)}.  IntentService
 * will receive the Intents, launch a worker thread, and stop the service as
 * appropriate.
 *
 * <p>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.
 *
 * @see android.os.AsyncTask
 */
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);
    }

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

    /**
     * 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.
     *
     * @param intent The value passed to {@link
     *               android.content.Context#startService(Intent)}.
     */
    protected abstract void onHandleIntent(Intent intent);
}
看到了,很简单也很简洁的代码。更令我惊喜的是它的Class doc

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.
这个家伙简直就是为了下载这类任务准备的啊,它是异步处理工作的服务,还能自动关闭回收。

工作流程也非常简单,客户端通过startService(Intent) 方法来调用,服务启动后,开启worker线程来顺序处理intent的任务。注意这里,一个intentService可以处理多个任务,只不过是一个接着一个的顺序来处理的;AsyncTask通常情况是每个任务启动一个新的asycnTask来工作,一个asyncTask只能使用一次,当你想再次使用的话,只好再new一个任务,否则要报异常的。从表象上看,这是两者的区别。当任务完成后,IntentService自动停止。
IntentService是继承自Service的,从源码上看,它是Service、HandlerThread和Handler的强强联合。源码也比AsyncTask简单,有兴趣的童鞋可以去看看。

下面说说它的用法,和AsyncTask一样,使用IntentService必须要写一个类然后继承它。
因为IntentService本身是继承自Service,所以在使用的时候要先在AndroidManifest.xml中注册,否则报错:Unable to start service Intent not found
IntentService有7个方法,其中最重要的是onHandleIntent(),在这里调用worker线程来处理工作,每次只处理一个intent,像上面描述的,如果有多个,它会顺序处理,直到最后一个处理完毕,然后关闭自己。一点都不用我们操心,多好。
再介绍另一个很有意思的方法,setIntentRedelivery()。从字面理解是设置intent重投递。如果设置为true,onStartCommand(Intent, int, int)将会返回START_REDELIVER_INTENT,如果onHandleIntent(Intent)返回之前进程死掉了,那么进程将会重新启动,intent重新投递,如果有大量的intent投递了,那么只保证最近的intent会被重投递。这个机制也很好,大家可以尝试着用。


andorid提供这个处理耗时任务的工具,为我们开发者带来了极大的便利。跟随源码,又可以让我们的水平上升一个档次。看来,android提供的文档和例子就是一个宝库,我们要好好的利用起来!同时一些源码也可以作为我们构造某个功能模块的模板样例!



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值