您的位置:首页 > 移动开发 > Android开发

IntentSerivce实现原理

2016-05-14 20:42 435 查看
1、Service的作用
Service存的理由是接手复杂耗时的计算任务,将其与UI部分隔离。不过,Service运行在主线程中,所以需要在其中单独创建额外后台线程来处理这些任务,避免占用UI线程,导致界面无响应。

2、IntentServic的作用
首先,它是一个Service,具备Service该有的功能。
其它,它封闭了后台线程的创建、关闭操作,提供了一个简单的将操作交给Serivce操作的方法。
所以,有时候使用它会比较方便,少写一些代码。但其功能是受限的,有它所适用的场景。

3、简要理解IntentSerivce的原理
用一句话来说:就是专门创建一个自带Looper的线程,接受并处理向IntentService发过来的各种消息。

4、实现原理
1)、通过Message-Handler-Looper实现主线程和后台线程的通信
要注意的是:在后台线程中构造Looper,然后不停的接收消息处理; 然后主线程向其发送消息。而不是常见的在后台线程中向主线程发送消息,刷新UI这种方式。

2)、带Looper的HandlerThread(工作线程)
HandlerThread是一个线程,继承自Thread。
public class HandlerThread extends Thread {
该线程唯一要做的事情就是创建Looper,然后进入消息循环,不停的处理接收到的消息。

@Override
public void run() {

    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {

        mLooper = Looper.myLooper();
        notifyAll();
    }

    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}
然后在IntentService中创建该线程并运行。

HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
3)、一个可向HandlerThread发消息的Handler
通常情况下,创建Handler时不指定Looper,则默认为将通过该Handler将消息发送至主线程的消息循环处理。然而,现在需要向HandlerThread发消息。所以,需要指定Looper。

mServiceLooper = thread.getLooper();

mServiceHandler = new ServiceHandler(mServiceLooper);
4)、ServiceHandler的实现
创建Handler时,必须要实现onHandlerIntent(),以便在其中进行消息处理。ServiceHandler中也是如此,不过在其中的消息处理非常简单,就是处理下消息,然后调用Service.stopSelf()停止IntentSerivce。

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)、onHandlerIntent具体做什么
这个交给具体的应用,其被定义为抽像方法。
所以,[b]这就决定了在使用IntentSerivce时,必须从它继承,然后再实现onHandleIntent()方法。在onHandleIntent()中运行的代码全部在HandlerThread中运行


protected abstract void onHandleIntent(Intent intent);
6)、如何发消息给ServiceHandler
通过多次调用startSerive(intent),可启动Service。如果Service没有启动,则会先创建,再启动,再调用onStartCommand(intent); 如果已经启动了,则会直接调用onStartCommand()。在onStartCommand()中会调用onStart(),在其中会向ServiceHandler发送消息。

public void onStart(Intent intent, int startId) {

    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

为什么不直接在onStartCommand()发送消息。查看Service源码可看到,onStart已经被废弃,可能是想兼容以前的代码吧。
7)、IntentService会在每次接受到消息时启动,处理完后结束自己么?
不会。多次调用startSerive(intent),并不会导致Service多次启动,而只会多次调用onStartCommand(intent),所有的Intent()都会通过mSerivceHander发送至HandlerThread的消息队列。
每次onHandlerIntent()处理完消息后,虽然会调用

stopSelf(msg.arg1);

但是只有在所有的请求全部处理完毕后,才会结束当前服务。

8)、IntentSerivce可以Bind吗
为什么不可以?Serivce可以同时bind和start。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android Service