天天看点

Android开发中IntentService的使用

 IntentService实现原理及内部代码 

Android中除了Service还有一个IntentService,他们之间到底有哪些区别呢? 在继承关系上而言IntentService是Service的子类,内部实现的代码中涉及到一些Android入门开发者不了解的Looper,Android123在早期的文章中已经说明他们的用法,这里不再赘述,有关原理大家可以看源码实现如下:

public abstract class IntentService extends Service {

    private volatile Looper mServiceLooper;

    private volatile ServiceHandler mServiceHandler; //一个Handler封装了Looper对象

    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);

        }

    }

    public IntentService(String name) { //构造方法,需要提供一个name作为标识

        super();

        mName = name;

    }

  对于下面的setIntentRedelivery的参数,如果为真时

onStartCommand(Intent, int, int)} will return

Service#START_REDELIVER_INTENT}, so if this process dies before

onHandleIntent(Intent)} returns, the process will be restarted

如果为假时

onStartCommand(Intent, int, int)} will return

Service#START_NOT_STICKY}, and if the process dies

     public void setIntentRedelivery(boolean enabled) {

        mRedelivery = enabled;

    }

    @Override

    public void onCreate() { //这里重写父类Service的创建,主要是构造一个线程

        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) {  //Android 2.0以前的Service启动参数控制

        Message msg = mServiceHandler.obtainMessage();

        msg.arg1 = startId;

        msg.obj = intent;

        mServiceHandler.sendMessage(msg);

    }

    @Override

    public int onStartCommand(Intent intent, int flags, int startId) { //Android 2.0以后的服务启动参数

        onStart(intent, startId);

        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;

    }

    @Override

    public void onDestroy() { //服务摧毁的时候Looper一定要释放掉,这点很重要。

        mServiceLooper.quit();

    }

    @Override

    public IBinder onBind(Intent intent) {

        return null;

    }

    protected abstract void onHandleIntent(Intent intent);

}

 从上面的代码相信大家可以看出IntentService和Service的不同了,通过Looper和Thread来解决标准Service中处理逻辑的阻塞问题,毕竟Android的Service也是会阻塞的。

关于使用

IntentService是Service类的子类,用来处理异步请求。客户端可以通过startService(Intent)方法传递请求给IntentService,IntentService通过worker thread处理每个Intent对象,执行完所有的工作之后自动停止Service。

说明:worker thread处理所有通过传递过来的请求,创建一个worker queue,一次只传递一个intent到onHandleIntent中,从而不必担心多线程带来的问题。处理完毕之后自动调用stopSelf()方法;默认实现了Onbind()方法,返回值为null;

模式实现了哦你StartCommand()方法,这个方法会放到worker queue中,然后在onHandleIntent()中执行0

使用IntentService需要两个步骤:

1、写构造函数

2、复写onHandleIntent()方法

好处:处理异步请求的时候可以减少写代码的工作量,比较轻松地实现项目的需求

    用Service来处理后台耗时操作,却很少注意到还有个IntentService

    首先IntentService是继承自Service的,那我们先看看Service的官方介绍,这里列出两点比较重要的地方:

      1.A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.

      2.A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).

      稍微翻一下(英文水平一般

Android开发中IntentService的使用

)

      1.Service不是一个单独的进程 ,它和应用程序在同一个进程中。

      2.Service不是一个线程,所以我们应该避免在Service里面进行耗时的操作

关于第二点我想说下,不知道很多网上的文章都把耗时的操作直接放在Service的onStart方法中,而且没有强调这样会出现Application Not Responding!希望我的文章能帮大家认清这个误区(Service不是一个线程,不能直接处理耗时的操作)。

       有人肯定会问,那么为什么我不直接用Thread而要用Service呢?关于这个,大家可以网上搜搜,这里不过多解释。有一点需要强调,如果有耗时操作在Service里,就必须开启一个单独的线程来处理!!!这点一定要铭记在心。  

       IntentService相对于Service来说,有几个非常有用的优点,首先我们看看官方文档的说明:

         IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests throughstartService(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.

         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 onHandleIntent(Intent). 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.

            稍微翻译理一理,这里主要是说IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程,这里就给我们提供了一个思路,如果有耗时的操作与其在Service里面开启新线程还不如使用IntentService来处理耗时操作。下面给一个小例子:

  1  Service:

  1. package com.zhf.service;
  2. import Android.app.Service;
  3. import Android.content.Intent;
  4. import Android.os.IBinder;
  5. public class MyService extends Service {
  6. @Override
  7. public void onCreate() {
  8. super.onCreate();
  9. }
  10. @Override
  11. public void onStart(Intent intent, int startId) {
  12. super.onStart(intent, startId);
  13. //经测试,Service里面是不能进行耗时的操作的,必须要手动开启一个工作线程来处理耗时操作
  14. System.out.println("onStart");
  15. try {
  16. Thread.sleep(20000);
  17. } catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. System.out.println("睡眠结束");
  21. }
  22. @Override
  23. public IBinder onBind(Intent intent) {
  24. return null;
  25. }
  26. }

2.IntentService:

  1. package com.zhf.service;
  2. import Android.app.IntentService;
  3. import Android.content.Intent;
  4. public class MyIntentService extends IntentService {
  5. public MyIntentService() {
  6. super("yyyyyyyyyyy");
  7. }
  8. @Override
  9. protected void onHandleIntent(Intent intent) {
  10. // 经测试,IntentService里面是可以进行耗时的操作的
  11. //IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent
  12. //对于异步的startService请求,IntentService会处理完成一个之后再处理第二个
  13. System.out.println("onStart");
  14. try {
  15. Thread.sleep(20000);
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. System.out.println("睡眠结束");
  20. }
  21. }

测试主程序:

  1. package com.zhf.service;
  2. import Android.app.Activity;
  3. import Android.content.Intent;
  4. import Android.os.Bundle;
  5. public class ServiceDemoActivity extends Activity {
  6. @Override
  7. public void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.main);
  10. startService(new Intent(this,MyService.class));//主界面阻塞,最终会出现Application not responding
  11. //连续两次启动IntentService,会发现应用程序不会阻塞,而且最重的是第二次的请求会再第一个请求结束之后运行(这个证实了IntentService采用单独的线程每次只从队列中拿出一个请求进行处理)
  12. startService(new Intent(this,MyIntentService.class));
  13. startService(new Intent(this,MyIntentService.class));
  14. }
  15. }

本文来陈瑞轩的博客,转载请标明出处:http://www.chenruixuan.com/?post=284