IntentService 面试详解

前两篇文章介绍了AsyncTask与HandleThread,主要是针对Android的多线程编程。在这里补充下线程的知识。
线程是操作系统调度的最小单元,同时也是一种受限的资源(即不能无限制的创建和销毁,创建和销毁都会占用系统资源)。操作系统是通过时间片轮转的方式调度每个线程,因此不可能做到绝对的并行。
进程一般指一个执行单元,在PC或移动设备上指一个程序或者应用。一个进程可以包含一个或多个线程。
Android中的线程分为主线程和子线程。主线程处理界面相关的操作,子线程用于处理耗时操作。特性:在UI线程(主线程)中执行耗时操作,会出现ANR,即Android应用无响应。所以不能在程中执行耗时的操作。


IntentService的内容如下:
1.什么是IntentService?
2.IntentService的使用方式
3.IntentService源码分析


1.什么是IntentService?
IntentService是Android提供的一个抽象类,继承了Service,是一种特殊的Service。必须创建子类才能使用IntentService。它的启动方式和一般的service一样,同时在IntentService中有一个工作线程用来处理异步请求。
作用:处理异步请求,实现多线程。它有优先级较高,用执行高优先级的任务。
特点:用于执行后台耗时任务,执行完毕自动停止。

IntentServic的工作流程:
这里写图片描述
注意:多次创建IntentService,其后台任务是以队列的方式在IntentService的onHandleIntent回调方法中顺序执行,执行完毕后自动停止。


2.IntentService的使用方式
使用步骤如下:
① 定义IntentService的子类:传入线程名称、复写onHandleIntent()方法
② 在Manifest.xml中注册服务
③ 在Activity中开启Service服务
具体实例如下:
创建IntentService的子类,并实现onHandleIntent(),方法。

public class myIntentService extends IntentService {

    /*构造函数*/
    public myIntentService() {
        //调用父类的构造函数
        //构造函数参数=工作线程的名字
        super("myIntentService");

    }

    /*复写onHandleIntent()方法*/
    //实现耗时任务的操作
    @Override
    protected void onHandleIntent(Intent intent) {
        //根据Intent的不同进行不同的事务处理
        String taskName = intent.getExtras().getString("taskName");
        switch (taskName) {
            case "task1":
                Log.i("myIntentService", "do task1");
                break;
            case "task2":
                Log.i("myIntentService", "do task2");
                break;
            default:
                break;
        }

    @Override
    public void onCreate() {
        Log.i("myIntentService", "onCreate");
        super.onCreate();
    }

    /*复写onStartCommand()方法*/
    //默认实现将请求的Intent添加到工作队列里
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("myIntentService", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i("myIntentService", "onDestroy");
        super.onDestroy();
    }
}

在Manifest.xml文件中注册

<service android:name=".myIntentService">
    <intent-filter>
        <action android:name="cn.scu.finch"/>
    </intent-filter>
</service>

最后在Activity中启动;

//同一服务只会开启一个工作线程
//在onHandleIntent函数里依次处理intent请求。
        Intent i = new Intent("cn.scu.finch");
        Bundle bundle = new Bundle();
        bundle.putString("taskName", "task1");
        i.putExtras(bundle);
        startService(i);

        Intent i2 = new Intent("cn.scu.finch");
        Bundle bundle2 = new Bundle();
        bundle2.putString("taskName", "task2");
        i2.putExtras(bundle2);
        startService(i2);

        startService(i);  //多次启动

结果为:
这里写图片描述
根据执行结果可以看到,它启动了多次,但任务都是顺序执行。


3.IntentService源码分析

// IntentService源码中的 onCreate() 方法
@Override
public void onCreate() {
    super.onCreate();
    // HandlerThread继承自Thread,内部封装了 Looper
    //通过实例化HandlerThread新建线程并启动
    //所以使用IntentService时不需要额外新建线程
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();

    //获得工作线程的 Looper,并维护自己的工作队列
    mServiceLooper = thread.getLooper();
    //将上述获得Looper与新建的mServiceHandler进行绑定
    //新建的Handler是属于工作线程的。
    mServiceHandler = new ServiceHandler(mServiceLooper);
}

private final class ServiceHandler extends Handler {

    public ServiceHandler(Looper looper) {
        super(looper);
    }

    // IntentService的handleMessage方法把接收的消息交给onHandleIntent()处理
    // onHandleIntent()是一个抽象方法,使用时需要重写的方法
    @Override
    public void handleMessage(Message msg) {
        // onHandleIntent 方法在工作线程中执行,执行完调用 stopSelf() 结束服务。
        onHandleIntent((Intent) msg.obj);
        //onHandleIntent 处理完成后 IntentService会调用 stopSelf() 自动停止。
        stopSelf(msg.arg1);
    }
}

// onHandleIntent()是一个抽象方法,使用时需要重写的方法
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
public int onStartCommand(Intent intent, int flags, int startId) {
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

public void onStart(Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    //把 intent 参数包装到 message 的 obj 中,然后发送消息,即添加到消息队列里
    //这里的Intent 就是启动服务时startService(Intent) 里的 Intent。
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

//清除消息队列中的消息
@Override
public void onDestroy() {
    mServiceLooper.quit();
}

我们来捋一下源码:IntentService本质是采用Handler + HandlerThread方式

首先是onCreat方法,通过HandlerThread单独开启一个名为IntentService的线程,创建一个名叫ServiceHandler的内部Handler,再将这两者绑定。这样IntentService中就可以使用 HandlerThread,并使用Handle传递消息。在ServiceHandler中的handleMessage方法中调用了抽象方法onHandleIntent(),这样,我们就能通过重写onHandleIntent()处理耗时任务了。

然后在onStartCommand()中传递给服务intent,顺序插入到工作队列中,发送给onHandleIntent(),通过onHandleIntent()来顺序处理Intent请求对象所对应的任务。

工作队列中的任务是顺序执行的。因为onCreate() 方法只会调用一次,所以只会创建一个工作线程,多次开启服务不会创建更多的线程,只是将消息添加到消息队列的等待执行。
但如果服务停止的话,会清空队列里的消息,不再执行。
最常使用场景:离线下载

一些对比:
IntentService与Service的区别

Service:依赖于应用程序的主线程(不是独立的进程 or 线程)
IntentService:创建一个工作线程来处理多线程任务  
Service需要主动调用stopSelft()来结束服务,而IntentService在所有intent被处理完后,会自动关闭

IntentService与其他线程的区别

IntentService内部采用了HandlerThread实现,作用类似于子线程;
与后台线程相比,IntentService是一种后台服务,优势是:优先级高(不容易被系统杀死),从而保证任务的执行。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值