异步消息处理基本用法
-
准备
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()
方法在其中打印一行日志,
证实服务是不是停止掉
了。
接着注册:


利用Intent可实现Service的启动,同普通Service:

主线程的 id
,用于同方才说的
IntentService
中onHandleIntent()
方法中打印的线程id
进行对比;
网友评论