IntentService源码分析

来源:互联网 发布:ubuntu ports 源 编辑:程序博客网 时间:2024/06/06 01:15

IntentService继承了Service并且是一个抽象类,需要创建它的子类才能使用IntentService。它相对Service来说,是一个特殊的Service,它的内部使用HandleThread

来执行服务,任务执行完,IntentService会自动退出。相对于Thread来说,它是一个服务,它的优先级高于线程,不容易被系统回收。

一个面试问题:我要用服务下载apk,是用IntentService,还是Service好?为什么?

IntentService与Service都可以执行下载apk的任务。具体的下载代码可以观看我的文章:IntentService、Service下载的apk。在回答这可问题之前我们要再次回顾一下Service的概念。Service是一种计算型组件,用于在后台执行一系列计算任务。Service不是一个线程,尽管它是执行后台计算的,它是运行在主线程中,耗时的后台操作仍然需要在单独的子线程中去执行,所以不要在Service的onStart方法中执行耗时操作,不然会出现Application Not Responding!的异常。而IntentService采用队列的方式将请求的Intent加入队列,然后开启一个线程来处理队列中的Intent,对于异步的startService请求。IntentService处理完一个后再处理第二个,都是在子线程中,不会阻塞主线程。所以有耗时操作与其在Service里开启子线程不如在IntentService中处理耗时操作。

回到主题,继续分析IntentService。

在IntentService的onCreate()方法中,可以看到它实现了HandleThread 和Handle。

private volatile Looper mServiceLooper;    private volatile ServiceHandler mServiceHandler;   @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);    }

IntentService第一次启动时,onCreate()方法调用,创建一个HandlerThread,获取到mServiceLooper,mServiceHandler。通过mServiceHandler发送信息会在HandlerThread中执行。每次启动IntentService,会调用onStartCommand()。IntentService在onStartCommand()方法中处理后台的Intent。在源码中onStartCommand调用了onStart():

 @Override    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {        onStart(intent, startId);        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;    } @Override    public void onStart(@Nullable Intent intent, int startId) {        Message msg = mServiceHandler.obtainMessage();        msg.arg1 = startId;        msg.obj = intent;        mServiceHandler.sendMessage(msg);    }

IntentService通过mServiceHandler发送了一条信息,消息会在HandleThread方法中处理。同时将Intent对象给 ServiceHandler的onHandleIntent方法处理。onHandleIntent是运行在子线程中,可以做耗时操作。另外这里的Intent对象和外界startService(intent)保持一致,通过它可以获得外界启动IntentService传递的参数,可以区分具体的后台任务,对不同的后台采取不同的处理方式(可以咱参照文章后边的样例)。onHandleIntent方法执行完之后,会调用stopSelf(int startId)停止服务。stopSelf()会立即停止服务,stopSelf(int startId)会等待所有信息都处理完后才关闭服务,它在服务关闭前会判断最近启动的次数是否与startId相等,相等立即停止服务,不相等不停止服务。

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);        }    }//This method is invoked on the worker thread with a request to process.  @WorkerThread    protected abstract void onHandleIntent(@Nullable Intent intent);

onHandleIntent是一个抽象方法,需要在子类中实现,它的作用就是区分Intent中的参数来区分任务并执行。在执行完onHandleIntent方法后,如果目前只有一个后台任务会立刻调用stopSelf(int startId)停止服务。如果有多个,会在onHandleIntent执行完最后一个任务后调用停止服务。每执行一个后台任务都会启动一次IntentService,而IntentService内部的信息是通过HandleThread来执行,Handle中的Looper顺序处理信息,所以IntentService是顺序执行后台任务的。多后台任务会按照外界发起的顺序排队执行。

public class DemoIntentService extends IntentService {    static final String Tag = "DemoIntentService";    public DemoIntentService() {        super("demo-intentService");    }    @Override    protected void onHandleIntent(Intent intent) {        String action = intent.getStringExtra("test_action");        Log.e(Tag, "receive action=====" + action);        try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }    }    @Override    public void onDestroy() {        Log.e(Tag, "onDestroy=====");        super.onDestroy();    }}
public class TestActivity extends Activity {    BroadcastReceiver receiver;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);Intent mIntent = new Intent(this, DemoIntentService.class);        mIntent.putExtra("test_action","action1");        startService(mIntent);        mIntent.putExtra("test_action","action2");        startService(mIntent);        mIntent.putExtra("test_action","action3");        startService(mIntent);    }}
注册列表<service android:name=“.downloadApk.DemoIntentService"/>

打印结果:

05-16 23:53:12.219 18007-18292/? E/DemoIntentService: receive action=====action1

05-16 23:53:13.219 18007-18292/? E/DemoIntentService: receive action=====action2

05-16 23:53:14.219 18007-18292/? E/DemoIntentService: receive action=====action3

05-16 23:53:15.219 18007-18007/? E/DemoIntentService: onDestroy=====

日志显示三个后台任务顺序执行,在action3后,执行stopSelf(int startId)。

=====================================>

这是一篇对书笔记,文章内容大多数来自于androdi开发艺术探索,很不错的一本书。

原创粉丝点击