[Android知识体系]之四大组件:service(intentService)

来源:互联网 发布:windows正版价格 编辑:程序博客网 时间:2024/05/18 02:33

IntentService 是比较少使用的,所以之前也一直没听说过它,不过前段时间整理android知识体系时看到有一小块是它的部分,所以查了资料对intentService做了点整理。

下面开始正文:

不管是何种Service,它默认都是在应用程序的主线程(亦即UI线程)中运行的。所以,如果你的Service将要运行非常耗时或者可能被阻塞的操作时,你的应用程序将会被挂起,甚至会出现ANR错误。为了避免这一问题,你应该在Service中重新启动一个新的线程来进行这些操作。现有两种方法共大家参考:

方法一:直接在Service的onStartCommand()方法中重启一个线程来执行,如

@Override      public int onStartCommand(Intent intent, int flags, int startId) {          MyServiceActivity.updateLog(TAG + " ----> onStartCommand()");          new Thread(new Runnable() {              @Override              public void run() {                  // 此处进行耗时的操作,这里只是简单地让线程睡眠了1s                  try {                      Thread.sleep(1000);                  } catch (Exception e) {                      e.printStackTrace();                  }              }          }).start();          return START_STICKY;      }  

方法二:Android SDK 中为我们提供了一个现成的Service类来实现这个功能,它就是IntentService,它主要负责以下几个方面:

-Creates a default worker thread that executes all intents delivered to onStartCommand() separate from your application’s main thread.
生成一个默认的且与主线程互相独立的工作者线程来执行所有传送至 onStartCommand() 方法的Intetnt

-Creates a work queue that passes one intent at a time to your onHandleIntent() implementation, so you never have to worry about multi-threading.
生成一个工作队列来传送Intent对象给你的onHandleIntent()方法,同一时刻只传送一个Intent对象,这样一来,你就不必担心多线程的问题。

-Stops the service after all start requests have been handled, so you never have to call stopSelf().
在所有的请求(Intent)都被执行完以后会自动停止服务,所以,你不需要自己去调用stopSelf()方法来停止该服务

-Provides default implementation of onBind() that returns null.
提供了一个onBind()方法的默认实现,它返回null

-Provides a default implementation of onStartCommand() that sends the intent to the work queue and then to your onHandleIntent() implementation
提供了一个onStartCommand()方法的默认实现,它将Intent先传送至工作队列,然后从工作队列中每次取出一个传送至onHandleIntent()方法,在该方法中对Intent对相应的处理

以上,英文来自官方SDK,中文为翻译。

还是有点乱七八糟的感觉吧?稍微总结一下:

IntentService 是继承自 Service 并处理异步请求的一个类,在 IntentService 内有一个独立的工作线程来处理耗时操作,当任务执行完后,IntentService 会自动停止,不需要我们去手动结束。如果启动 IntentService 多次,那么每一个耗时操作会以工作队列的方式在 IntentService 的 onHandleIntent 回调方法中执行,依次去执行,执行完自动结束

哈哈,这样再来看官方文档的介绍,是不是感觉就清晰很多了呢?


从以上看来,你所需要做的就是实现 onHandleIntent() 方法,在该方法内实现你想进行的操作。另外,继承IntentService时,你必须提供一个无参构造函数,且在该构造函数内,你需要调用父类的构造函数,如下:

public HelloIntentService() {            super("HelloIntentService");    }  

嘤嘤嘤,那么怎么使用呢?官方的解释是这样的:

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

4级没过,看不懂,那么来看看翻译吧:

IntentService是一个通过Context.startService(Intent)启动可以处理异步请求的Service,使用时你只需要继承IntentService和重写其中的onHandleIntent(Intent)方法接收一个Intent对象,在适当的时候会停止自己(一般在工作完成的时候). 所有的请求的处理都在一个工作线程中完成,它们会交替执行(但不会阻塞主线程的执行),一次只能执行一个请求.(简略翻译,不要见怪)

现在开始正式的应用:

intentService使用

举例:

// activity 的onCreate()  @Override      public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.main);          startSer1 = (Button) findViewById(R.id.startSer1);          stopSer1 = (Button) findViewById(R.id.stopSer1);          startSer2 = (Button) findViewById(R.id.startSer2);          stopSer2 = (Button) findViewById(R.id.stopSer2);          log = (TextView) findViewById(R.id.log);          logView = (ScrollView) findViewById(R.id.logView);          startSer1.setOnClickListener(btnListener);          stopSer1.setOnClickListener(btnListener);          startSer2.setOnClickListener(btnListener);          stopSer2.setOnClickListener(btnListener);          intent = new Intent(MyServiceActivity.this, IntentServiceDemo.class);          // 打印出主线程的ID          long id = Thread.currentThread().getId();          updateLog(TAG + " ----> onCreate() in thread id: " + id);      }  
// service 代码  package com.archer.rainbow;  import java.text.SimpleDateFormat;  import java.util.Date;  import android.app.IntentService;  import android.content.Intent;  public class IntentServiceDemo extends IntentService {      private static final String TAG = "IntentServiceDemo";      private static final SimpleDateFormat SDF_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss.SSS");      public IntentServiceDemo() {          super(TAG);          MyServiceActivity.updateLog(TAG + " ----> constructor");      }      @Override      public void onCreate() {          super.onCreate();          // 打印出该Service所在线程的ID          long id = Thread.currentThread().getId();          MyServiceActivity.updateLog(TAG + " ----> onCreate() in thread id: "                  + id);      }      @Override      public void onDestroy() {          super.onDestroy();          MyServiceActivity.updateLog(TAG + " ----> onDestroy()");      }      @Override      public int onStartCommand(Intent intent, int flags, int startId) {          MyServiceActivity.updateLog(TAG + " ----> onStartCommand()");          // 记录发送此请求的时间          intent.putExtra("time", System.currentTimeMillis());          return super.onStartCommand(intent, flags, startId);      }      @Override      public void setIntentRedelivery(boolean enabled) {          MyServiceActivity.updateLog(TAG + " ----> setIntentRedelivery()");          super.setIntentRedelivery(enabled);      }      @Override      protected void onHandleIntent(Intent intent) {          // 打印出处理intent所用的线程的ID          long id = Thread.currentThread().getId();          MyServiceActivity.updateLog(TAG                  + " ----> onHandleIntent() in thread id: " + id);          long time = intent.getLongExtra("time", 0);          Date date = new Date(time);          try {              // 打印出每个请求对应的触发时间              MyServiceActivity.updateLog(TAG                      + " ----> onHandleIntent(): 下载文件中..." + SDF_DATE_FORMAT.format(date));              Thread.sleep(3000);          } catch (InterruptedException e) {              e.printStackTrace();          }      }  }  

应用启动时,界面如下:
应用启动界面

从此图可以看出,主线程(UI线程)的ID是1。接着,连续点击三次Start Service 1 按钮,得如下画面:

连续点击三次Start Service 1 按钮界面

从此图中可以看出,IntentServiceDemo的onCreate()所处的线程ID仍为1,说明它是在主线程中被执行的,且只被执行一次。然后,我每点击一次按钮,它都会触发一下onStartCommand()方法。仔细看第二次与第三次的onCommand()方法以及onHandleIntent()打印出来的语句,你会发现,第二、三两次点击按钮与第一次点击按钮的时间是没有超过3秒钟的,它们是连续被执行的,这说明了什么呢?说明,在第一个intent被处理时(即onHandleIntent()处于运行中),该Service仍然可以接受新的请求,但接受到新的请求后并没有立即执行,而是将它们放入了工作队列中,等待被执行。

这就是 IntentService 的简单用法。但你若是想在Service中让多个线程并发的话,就得另想法子。比如,使用第一种方法,在Service内部起多个线程,但是这样的话,就要处理好线程的同步啦~~

0 0
原创粉丝点击