IntentService(二)

来源:互联网 发布:飞利浦e5音响 知乎 编辑:程序博客网 时间:2024/06/05 09:04

此篇讲述IntentService的简单使用


什么是IntentService,首先看看官方的解释:

IntentService is a base class forServices that handle asynchronous requests (expressed asIntents) 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



简单说,IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们去手动控制。另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

还有一个说明是:

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.

大致意思是:所有请求都在一个单线程中,不会阻塞应用程序的主线程(UI Thread),同一时间只处理一个请求。


1.清单文件中注册

<service android:name="com.finddreams.runningman.MyIntentService">
 </service>


2.java代码中实现IntentService

package com.finddreams.runningman;


import android.app.IntentService;
import android.content.Intent;
import android.util.Log;


public class MyIntentService extends IntentService{


//构造方法1 错误
// public MyIntentService(String name) {
// super(name);
// Log.d("MyIntentService", "构造方法!!!!!!!!Thread----:"+Thread.currentThread().getName());
// }


//构造方法2 正确
public MyIntentService() {
super("MyIntentService");
Log.d("MyIntentService", "构造方法!!!!!!!!Thread----:"+Thread.currentThread().getName());
}

//onCreate方法
@Override
public void onCreate() {
super.onCreate();
Log.d("MyIntentService", "onCreate方法!!!!!!!!Thread----:"+Thread.currentThread().getName());
}

//onStartCommand方法 
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyIntentService", "onStartCommand方法!!!!!!!!Thread----:"+Thread.currentThread().getName());
return super.onStartCommand(intent, flags, startId);
}

//onHandleIntent方法 耗时操作
@Override
protected void onHandleIntent(Intent arg0) {
String name=arg0.getStringExtra("name");
String age=arg0.getStringExtra("age");
//耗时操作 比如 下载文件 链接网络 下载图片...

Log.d("MyIntentService", "name----:"+name);
Log.d("MyIntentService", "age----:"+age);
Log.d("MyIntentService", "onHandleIntent方法!!!!!!!!Thread----:"+Thread.currentThread().getName());
}


}


3.java 代码中启动服务

Intent intent=new Intent(RuningManActivity.this,MyIntentService.class);
intent.putExtra("name", "张三");
intent.putExtra("age", "18");
startService(intent); 


4.结果



5.说明

5.1.通过以上的输出结果我们可以发现,MyIntentService的onCreate、onStartCommand、onDestroy等回调方法都是运行在主线程中的,而onHandleIntent是运行在工作线程IntentService[MyIntentService]中的,这验证了我们上面所说的IntentService的第一个和第二个特点。即只有onHandleIntent方法运行在子线程中,其他生命周期方法和构造方法运行在UI线程。

5.2.如果我们连续调用了多次startService(intent)之后,onStartCommand依次被调用了多次,然后依次执行了onHandleIntent多次,这样就依次完成了job,当最后一个job完成,也就是在最后一次onHandleIntent调用完成之后,整个IntentService的工作都完成,执行onDestroy回调方法,IntentService销毁。


6.注意

IntentService的构造方法

public MyIntentService(String name) {
super(name);
Log.d("MyIntentService", "构造方法!!!!!!!!Thread----:"+Thread.currentThread().getName());
}

报错:

java.lang.RuntimeException: Unable to instantiate service com.finddreams.runningman.MyIntentService: java.lang.InstantiationException: can't instantiate class com.finddreams.runningman.MyIntentService; no empty constructor


IntentService的构造方法

public MyIntentService() {
super("MyIntentService");
Log.d("MyIntentService", "构造方法!!!!!!!!Thread----:"+Thread.currentThread().getName());
}

正确


6.IntentService工作原理及源码解析

在上面我们已经介绍了IntentService的特点以及如何使用,那么你可能会疑问Android是如何将调度这些intent将其传入onHandleIntent完成工作的,其实IntentService的工作原理很简单,将intent转换为Message并放到消息队列中,然后让Handler依次从中取出Message对其进行处理。

IntentService的源码如下:

package android.app;
 
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
 
public abstract class IntentService extends Service {
 private volatile Looper mServiceLooper;
 private volatile ServiceHandler mServiceHandler;
 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,确保onHandleIntent不会阻塞主线程
   onHandleIntent((Intent)msg.obj);
   //在执行完了onHandleIntent之后,我们需要调用stopSelf(startId)声明某个job完成了
   //当所有job完成的时候,Android就会回调onDestroy方法,销毁IntentService
   stopSelf(msg.arg1);
  }
 }
 
 public IntentService(String name) {
  //此处的name将用作线程名称
  super();
  mName = name;
 }
 
 public void setIntentRedelivery(boolean enabled) {
  mRedelivery = enabled;
 }
 
 @Override
 public void onCreate() {
  super.onCreate();
  //创建HandlerThread,利用mName作为线程名称,HandlerThread是IntentService的工作线程
  HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
  thread.start();
 
  mServiceLooper = thread.getLooper();
  //将创建的HandlerThread所绑定的looper对象传递给ServiceHandler,
  //这样我们创建的Handler就和HandlerThread通过消息队列绑定在了一起
  mServiceHandler = new ServiceHandler(mServiceLooper);
 }
 
 @Override
 public void onStart(Intent intent, int startId) {
  //在此方法中创建Message对象,并将intent作为Message的obj参数,
  //这样Message与Intent就关联起来了
  Message msg = mServiceHandler.obtainMessage();
  msg.arg1 = startId;
  msg.obj = intent;
  //将关联了Intent信息的Message发送给Handler
  mServiceHandler.sendMessage(msg);
 }
 
 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
  //IntentService重写了onStartCommand回调方法:在内部调用onStart回调方法
  //所以我们在继承IntentService时,不应该再覆写该方法,即便覆盖该方法,我们也应该调用super.onStartCommand()
  onStart(intent, startId);
  return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
 }
 
 @Override
 public void onDestroy() {
  //在onDestroy方法中调用了Handler的quit方法,该方法会终止消息循环
  mServiceLooper.quit();
 }
 
 @Override
 public IBinder onBind(Intent intent) {
  return null;
 }
 
 protected abstract void onHandleIntent(Intent intent);
}


我对上面的代码已经加了很多注释,相信大家直接看代码就能理解IntentService是如何运作的了。

IntentService继承自Service类,并且IntentService重写了onCreate、onStartCommand、onStart、onDestroy回调方法,并且IntentService还添加了一个onHandleIntent回调方法。下面我们依次解释这几个方法在IntentService的作用。

onCreate: 在onCreate回调方法中,利用mName作为线程名称,创建HandlerThread,HandlerThread是IntentService的工作线程。HandlerThread在执行了start方法之后,其本身就关联了消息队列和Looper,并且消息队列开始循环起来。

onStartCommand:IntentService重写了onStartCommand回调方法:在内部调用onStart回调方法。

onStart: 在onStart方法中创建Message对象,并将intent作为Message的obj参数,这样Message与Intent就关联起来了,然后通过Handler的sendMessage方法将关联了Intent信息的Message发送给Handler。

onHandleIntent:当在onStart方法中,通过sendMessage方法将Message放入到Handler所关联的消息队列中后,Handler所关联的Looper对象会从消息队列中取出一个Message,然后将其传入Handler的handleMessage方法中,在handleMessage方法中首先通过Message的obj获取到了原始的Intent对象,然后将其作为参数传给了onHandleIntent方法让其执行。handleMessage方法是运行在HandlerThread的,所以onHandleIntent也是运行在工作线程中的。在执行完了onHandleIntent之后,我们需要调用stopSelf(startId)声明某个job完成了。当所有job完成的时候,Android就会回调onDestroy方法,销毁IntentService。

onDestroy:当所有job完成的时候,Service会销毁并执行其onDestroy回调方法。在该方法中,调用了Handler的quit方法,该方法会终止消息循环。

总结

IntentService可以在工作线程中完成工作而不阻塞主线程,但是IntentService不能并行处理多个job,只能依次处理,一个接一个,当所有的job完成后,会自动执行onDestroy方法而无需我们自己调用stopSelf()或stopSelf(startId)方法。IntentService并不神秘,只是Android对一种常见开发方式的封装,便于开发人员减少开发工作量。 IntentService是个助手类,如果Android没有提供该类也没什么,我们自己也可以写一个类似的。IntentService之余Service,类似于HandlerThread之于Handler。


总结:IntentService和Service去了这样的差别之外,没有什么区别了,比如注册一样,启动方式一样(启动式 绑带式)等等。



0 0
原创粉丝点击