异步消息处理基本用法
- 准备
int常量用于标记某个任务; - 主线程实例化
Handler对象,
同时重写Handler的handleMessage()方法,
方法中通过使用if或者switch,
将(子线程发送的)Message的what字段
同一个或者以上的int任务标志常量做匹配,
调用对应的任务处理模块进行处理;
- 在对应的场景(如某个View的回调方法中):
利用匿名类的方式,通过Thread、Runnable()、run()、start()等类与方开启子线程,在子线程的线程任务执行单位(即run())中:
3.1. 实例化Message对象;
3.2. 将任务常量id设置到Message实例对象的what字段中;
3.3. 使用2.中定义的Handler实例调用sendMessage()将Message实例发送到MQ;
至此完成;
- 相关笔记:Tip | Android的消息机制

Service生命周期

onCreate():服务第一次被创建时调用onStartComand():服务启动时调用onBind():服务被绑定时调用onUnBind():服务被解绑时调用onDestroy():服务停止时调用
普通Service(开启Service的两个基本方法,其一)
- 新建一个类并令其继承Service且必须重写
onBind()方法,
有选择的重写onCreate()、onStartCommand()及onDestroy()方法;
- 在配置文件中进行注册;
或者直接按照以下方法则AS会自动注册:
- 在对应的场景(如某个View的回调方法中),
利用Intent可实现Service的启动:
Intent intent = new Intent(this, MyService.class);// MyService是刚刚定义好的Service
startService(intent);
Service的停止:
Intent intent = new Intent(this, MyService.class);
stopService(intent);
Service与Activity的通信(开启Service的两个基本方法,其二)
- 新建一个
类(如MyService)继承自Service并注册好; - 类中定义一个
内部类(如MyBinder)继承Binder,
在其内部编写要放在Service后台服务执行的逻辑方法模块;
- 在
继承自Service的类(MyService)中
实例化继承Binder的内部类(MyBinder)实例
并作为MyService的成员变量;
- 重写
onBind()方法,返回成员变量MyBinder实例; - 在对应
启动Service的活动中,
在活动中实例化一个ServiceConnection类对象,
并重写它的onServiceConnection()和onServiceDisconnection()方法,
这两个方法分别会在活动与服务成功绑定以及解除绑定的时候调用。
在onServiceConnected()方法中,
又通过向下转型得到了MyBinder的实例,
有了它就可以在活动中调用MyBinder中的任何非private方法了,
即实现Service与Activity的通信。
- 最后在在对应的场景(如某个View的回调方法中),
利用Intent对象以及下面两个方法
实现活动和服务的绑定和解绑:
bindService()实现绑定,
它接收三个参数(Intent对象,ServiceConnection对象,标志位),
这里传入BIND_AUTO_CREATE
表示在活动和服务进行绑定后自动创建服务,
unbindService()实现解绑,
传入ServiceConnection对象即可。



前台Service
前台Service类似通知,
只不过在构建好一个Notification之后,
不需要NotificationManager将通知显示出来,
而是调用了startForeground()方法。
可以在新建的继承Service的类的onCreate()方法中,如下编写:
启动方法同普通Service,即在对应的场景(如某个View的回调方法中)编写:
Intent intent = new Intent(this, MyService.class);// MyService是刚刚定义好的Service
startService(intent);
系统Service
除了自定义一个Service,可以使用现有的系统服务;
通过getSyetemService()方法并传入一个Name
即可得到相应的服务对象,
常用的系统服务如下表:
下面学习AlarmManager系统服务,实现一个后台定时任务
调用AlarmManager的set()方法就可以设置一个定时任务,set()有三个参数(工作类型,定时任务触发的时间,PendingIntent对象):
1)工作类型:有四个值可选:
2)定时任务触发的时间:以毫秒为单位,传入值和第一个参数对应关系:
3)PendingIntent对象:
一般会调用它的getBroadcast()方法来获取一个能够执行广播的PendingIntent。
这样当定时任务被触发的时候,
广播接收器中的onReceive()方法即可得到执行,
在onReceive()方法我们可以再次启动Service,
同时编写任务执行代码块;
实战使用时,
可以在新建的继承Service的类的onStartCommand()方法中,
如下编写:
注意这里的提供给PendingIntent的Intent
跳转到的广播接收器是需要我们自己定义的,
这里定义的接收器是MyBroadcast:
如此一来,
一旦启动MyService,
就会在onStartCommand()方法里设定一个定时任务,10秒后MyReceiver的onReceive()方法将被回调执行,
紧接着又反过来启动MyService,反复循环。
从而实现一个能长期在后台进行定时任务的服务。
同时在MyReceiver的onReceive()方法中
我们可以添加编写任务执行代码块;
另外,从Android 4.4版本开始,
由于系统在耗电性方面进行了优化使得Alarm任务的触发时间会变得不准确。
如果一定要求Alarm任务的执行时间精确,
把AlarmManager的setExact()方法替代set()方法就可以了。
IntentService
使用Android提供的IntentService,
可以简单地实现一个异步的、会自动停止的服务;
- 新建类并继承
IntentService,
类中提供一个无参的构造函数
且必须在其内部调用父类的有参构造函数;
然后重写onHandleIntent()方法,
里面可以处理一些耗时操作而不用担心 ANR的问题,
因为这个方法已经是在子线程中运行的了。
- 在配置文件中进行注册。
- 在活动中利用
Intent启动IntentService,同普通Service。
实战参考:
onHandleIntent()方法中为了证实这个方法确实已经在子线程中,
打印了当前线程的id与稍后与主线程的线程id作对比。
另外,IntentService的特性是在运行结束后应该是会自动停止,
这里重写onDestroy()方法在其中打印一行日志,
证实服务是不是停止掉了。
接着注册:
或者直接按照以下方法则AS会自动注册:
在对应的场景(如某个View的回调方法中),
利用Intent可实现Service的启动,同普通Service:
在这里打印了主线程的 id,
用于同方才说的IntentService中onHandleIntent()方法中打印的线程id进行对比;