1. IntentService原理

IntentService是一种特殊的Service,既然是Service,使用的时候记得在AndroidManifest清单文件中注册。

并且它是一个抽象类,因此必须创建它的子类才能使用IntentService,IntentService可用于执行后台耗时的任务,当任务执行后它会自动停止,同时由于IntentService是服务的原因,这导致它的优先级比单纯的线程要高级很多,所以IntentService比较适合执行高优先级的后台任务,因为它的优先级高不容易被系统杀死。

在实现上,IntentService封装了HandlerThread 和 Handler,这一点我们可以在IntentService的onCreate方法看出来:

@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方法会被调用,onCreate方法会创建一个HandlerThread,然后利用它的Looper构造一个Handler对象mServiceHandler(ServiceHandler继承自Handler,ServiceHandler是IntentService内部类)

我们来到IntentService中的内部类ServiceHandler的实现源码如下:

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

这样通过mServiceHandler发送的消息都会最终在HandlerThread中执行,从这个角度来看,IntentService也可以用于执行后台任务。

每次启动IntentService,它的onStartCommand方法就会调用一次,IntentService在onStartCommand中处理每个后台任务的Intent。

接下来我们要看一下IntentService在OnStartCommand方法是如何处理外界的Intent的,如下:

  @Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

在上面源码中可以知道onStartCommand调用了onStart,我们再看看IntentService中onStart方法的实现如下所示:

@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}

上面的源码可以看出,在onStart方法之中,IntentService仅仅是通过mServiceHandler发送了一个消息,而mServiceHandler录属于HandlerThread的,所以这个消息会在HandlerThread这个线程之中被处理。

mServiceHandler收到消息之后,会将Intent对象传递给onHandleIntent方法去处理。

需要特别注意:

  这里的Intent对象的内容 和 外界的StartService(intent)中的intent的内容是完全一致的,通过这个Intent对象即可解析出外界启动IntentService时候所传递的参数,通过这些参数就可以区分具体的后台任务,这样在onHandleIntent方法中就可以对不同的后台任务做处理了。

当onHandleIntent方法执行结束之后,IntentService会通过stopSelf(int startId)方法尝试停止服务。这里之所以采用stopSelf(int startId)而不是stopSelf()来停止服务,那是因为stopSelf()会立刻停止服务,而这个时候可能还有其他消息未处理,stopSelf(int startId)则会等待所有的消息都处理完毕之后才终止服务。一般来说,stopSelf(int startId)在尝试停止服务之前会判断最近启动服务的次数是否和startId相等,如果相等就立刻停止服务,不相等则不停止服务。

IntentService的onHandleIntent方法是一个抽象方法,它需要在子类中实现,它的作用是从Intent参数中区分具体的任务并执行这些任务。如果目前只存在一个后台任务,那么onHandleIntent方法执行完整个任务之后,stopSelf(int startId)就会直接停止服务;如果目前存在多个后台任务,那么当onHandleIntent方法执行完最后一个任务时候,stopSelf(int startId)才会直接停止服务。

另外,由于每执行一个后台任务就必须启动一次IntentService,而IntentService内部则可以通过消息的方式向HandlerThread请求执行任务,Handler中的Looper是顺序处理消息的,这就意味着IntentService也是顺序执行后台任务的,当有多个后台任务同时存在,这些后台任务会按照外界发起的顺序排队执行。

总而言之,流程如下:

2. IntentService使用示例:

(1)新建Android工程如下:

(2)首先我们来到主Activity,如下:

package com.himi.intentservicedemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle; public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); /**
* 可以启动多次,每启动一次,就会新建一个work thread
* 但IintentService的实例始终只有一个
*/
// Operation 1
Intent startServiceIntent = new Intent(this,MyIntentService.class);
Bundle bundle = new Bundle();
bundle.putString("param", "oper1");
startServiceIntent.putExtras(bundle);
startService(startServiceIntent); // Operation 2
Intent startServiceIntent2 = new Intent(this,MyIntentService.class);
Bundle bundle2 = new Bundle();
bundle2.putString("param", "oper2");
startServiceIntent2.putExtras(bundle2);
startService(startServiceIntent2);
}
}

(3)其次这里在MainActivity中开启IntentService服务,但是它是个抽象类,需要一个IntentService具体实现子类,这里为MyIntentService,如下:

package com.himi.intentservicedemo;

import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder; public class MyIntentService extends IntentService { public MyIntentService() {
// 必须实现父类的构造方法
super("IntentServiceDemo");
} @Override
public IBinder onBind(Intent intent) {
System.out.println("onBind");
return super.onBind(intent);
} @Override
public void onCreate() {
System.out.println("onCreate");
super.onCreate();
} @Override
public void onStart(Intent intent, int startId) {
System.out.println("onStart");
super.onStart(intent, startId);
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("onStartCommand");
return super.onStartCommand(intent, flags, startId);
} @Override
public void setIntentRedelivery(boolean enabled) {
super.setIntentRedelivery(enabled);
System.out.println("setIntentRedelivery");
} @Override
protected void onHandleIntent(Intent intent) { //这个方法在子线程中执行,因此需要用到handler跟主线程进行通信
// Iintent是从Activity发过来的,携带识别参数,根据参数不同执行不同的任务
String action = intent.getExtras().getString("param");
if (action.equals("oper1")) {
System.out.println("Operation1");
} else if (action.equals("oper2")) {
System.out.println("Operation2");
} try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} @Override
public void onDestroy() {
System.out.println("onDestroy");
super.onDestroy();
} }

(4)最后很重要一步,别忘了配置IntentService,因为它继承于Service,所以,它还是一个Service,一定要配置,否则是不起作用的,在清单文件中配置一下IntentService,如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.himi.intentservicedemo"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="17" /> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> <service
android:name="MyIntentService">
</service> </application> </manifest>

(5)部署程序到手机上,观察Logcat如下:

  从结果可以看到,onCreate方法只执行了一次,而onStartCommand和onStart方法执行了两次,开启了两个Work Thread,这就证实了之前所说的,启动多次,但IntentService的实例只有一个,这跟传统的Service是一样的。Operation1也是先于Operation2打印,并且我让两个操作间停顿了2s,最后是onDestroy销毁了IntentService。

这就是IntentService,一个方便我们处理业务流程的类,它是一个Service,但是比Service更智能。

最新文章

  1. od 查看特殊格式的文件内容
  2. sublime text3的安装与汉化
  3. loading动画效果记录
  4. 解决&lt;a&gt;文本本身带下划线和超链接下划线重合的问题
  5. SharePoint 2013中Office Web Apps的一次排错
  6. spark-submit [options]
  7. poj-1469-COURSES-二分图匹配-匈牙利算法(模板)
  8. jquery来跨域提交表单
  9. ACM-进阶之路
  10. Mysql实时双备
  11. 用javascript操作xml
  12. 浅谈如何用Java操作MongoDB
  13. git错误记录及解决
  14. vue图片上传到七牛云
  15. 数字信号处理专题(1)——DDS函数发生器环路Demo
  16. setting-url配置
  17. POJ1905-Expanding Rods-二分答案
  18. webpack3--配置多入口和多出口
  19. 使用Spring Session和Redis解决分布式Session跨域共享问题
  20. Linux命令之rlogin

热门文章

  1. AutoCAD DxfCode组码值类型
  2. HDU 5437 Alisha’s Party (优先队列模拟)
  3. JavaServer Faces 2.2 requires Dynamic Web Module 2.5 or newer
  4. cf754 A. Lesha and array splitting
  5. EasyUI Accordion下的Panel面板初始化时全部折叠
  6. C#中的Collection 1
  7. js 数组去重 的5种方法
  8. maven中解决javax.servlet.jsp.PageContext cannot be resolved to a type
  9. Codeforces Gym 100187D D. Holidays 排列组合
  10. 汽车XX网站秒杀抢购代码