IntentService简析
来源:互联网 发布:手机自动录像软件 编辑:程序博客网 时间:2024/05/29 19:51
一、IntentService的使用
public class MyIntentService extends IntentService { private static final String TAG = "MyIntentService"; public MyIntentService() { super(TAG); println("MyIntentService()"); } @Override public void onCreate() { super.onCreate(); println("onCreate()"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { println("onStartCommand()"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { println("onDestroy()"); super.onDestroy(); } @Nullable @Override public IBinder onBind(Intent intent) { println("onBind()"); return super.onBind(intent); } @Override protected void onHandleIntent(Intent intent) { println("onHandleIntent()"); try { Thread.sleep(6000); } catch (Exception e) { e.printStackTrace(); } } private void println(String info) { System.out.println(TAG + " " + info); }}
实际上,如果需要使用IntentService,直接重写onHandleIntent(Intent intent)这个方法就行。不过在这里,主要是为了看看IntentService的生命周期,所以把IntentService的所有方法都重写了一遍,然后将相关的日志打印出来。
在onHandleIntent(Intent intent)里,就只打印了一行日志,然后将当前线程暂停6秒。为什么是6秒,因为在主线程中,如果暂停时间超过5秒,那么就会产生臭名昭著的ANR问题。在这里主要就是想看看,如果在这里线程暂停超过5秒,会不会产生ANR。
<service android:name=".service.MyIntentService"/>
首先在清单文件中将这个服务进行注册,然后通过一个按钮来启动服务。
startService(new Intent(this, MyIntentService.class));
启动服务之后,等待一段时间查看日志,日志如下
I/System.out: MyIntentService MyIntentService()I/System.out: MyIntentService onCreate()I/System.out: MyIntentService onStartCommand()I/System.out: MyIntentService onHandleIntent()I/System.out: MyIntentService onDestroy()
通过上述的日志可以看出,这个服务会自动停止,并且不会导致ANR问题。那么下面,我们将通过源码看看,为什么IntentService会自动停止,并且不会导致ANR问题。(在普通的Service中执行上述的Thread.Sleep(6000)将会导致ANR)。
二、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); }
在这里主要是启动一个HanderThread,这里我们称之为服务线程,然后给这个线程定义一个Handler(注意,这里不是给UI线程创建的Handler)。然后再看看onStartCommand()的实现。
@Override public int onStartCommand(Intent intent, int flags, int startId) { onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; }
这里很简单,先调用onStart(intent, startId),然后给一个返回值。那么我们直接去看onStart()里的实现好了。
@Override public void onStart(Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); }
先通过这个线程的Handler去获取一个消息,然后将startId,intent这些参数赋值给这个消息。通过服务线程的Handler将这个消息发送到这个线程的消息队列中去,然后这个线程中的Loop方法就会解除阻塞,获取到这个消息,并将这个消息交给这个消息指定的Handler进行处理。那么我们来看看这个handler的实现。
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); } }
在handleMessage(Message msg)实现比较简单,先是将启动这个服务的Intent从消息中取出,然后调用onHandleIntent((Intent)msg.obj)函数。onHandleIntent函数的定义在上面已经看过,很简单,就是打印一条日志,然后暂停6秒钟。onHandleIntent函数完成后,就会调用stopSelf(msg.arg1)来停止这个服务。
现在我们来梳理一下:
- 通过在onCreate()中启动一个HanlderThread线程(考虑一下,为什么不在onStartCommand中启动这个线程)。
- 在onStartCommand中获取startId和Intent,然后通过Handler获取消息,将startId和Intent设置在这个消息中,然后通过Handler将这个消息发送到消息队列中。
- 在loop()函数中,由于消息的入队,这个时候会解除阻塞,接收这个消息,然后将这个消息直接给这个Handler处理。
- 因为Handler是在服务线程中运行的,所以虽然在onHandleIntent中等待了6秒钟,但是由于不是在UI线程,所以不会导致ANR。
- 在执行完onHandleIntent后,IntentService会自动调用stopSlef来停止服务本身。
- IntentService简析
- IntentService
- IntentService
- intentservice
- IntentService
- IntentService
- IntentService
- IntentService
- IntentService
- IntentService
- IntentService
- IntentService
- IntentService
- IntentService
- IntentService
- IntentService
- IntentService
- IntentService
- 《浅谈架构之路:前后端分离模式》
- task_struct结构体详解
- Deeplearning4j 实战(4):Deep AutoEncoder进行Mnist压缩的Spark实现
- 一次Python性能调优经历
- UVA-10462-Is There A Second Way Left? (次小生成树带重边)
- IntentService简析
- FMDB使用方法
- 欢迎使用CSDN-markdown编辑器
- jdk配置法安装,让你更熟
- 475. Heaters
- 【Linux】用gcc生成静态库和动态库
- 素数筛法系列
- javaweb的servlet使用指南
- Web安全与防御措施