参考链接
Service
service生命周期
service有两个生命周期,为什么会有两个生命周期呢,这是根据service的启动方式来进行区分的。
Context.startService()
通过该方法启动service,访问者与service之间没有关联,即使访问者退出了,service也仍然运行。以下是打印结果
1 | com.app.demoservice I/MyService: onCreate: 开始创建Service |
Context.bindService(Intent service,ServiceConnection conn,int flags)
使用该方法启动的service,访问者与service绑定在一起,访问者退出,service也就终止了。
service的主要回调方法
IBinder onBind(Intent intent)
该方法是Service子类必须实现的方法,该方法返回一个IBinder对象,应用程序可通过该对象与Service组件通信。void onCreate()
在该Service第一次被创建后会立即回调该方法void onDestroy
在该Service被关闭之前会回调该方法void onStartCommand(Intent intent, int flags, int startId)
该方法的早期版本是onStart(Intent intent,int startId)
,每次客户端调用startService(Intent)
方法启动Service,都会回调该方法
多次调用startService(),会多次调用onStartCommand()1
2
3
4
5com.app.demoservice I/MyService: onCreate: 开始创建Service
com.app.demoservice I/MyService: onStartCommand: 每次调用startService()方法时,都会回调这个方法
com.app.demoservice I/MyService: onStartCommand: 每次调用startService()方法时,都会回调这个方法
com.app.demoservice I/MyService: onStartCommand: 每次调用startService()方法时,都会回调这个方法
com.app.demoservice I/MyService: onStartCommand: 每次调用startService()方法时,都会回调这个方法void onUnBind(Intent intent)
当Service与之绑定的客户端都断开连接时,会回调这个方法
绑定本地Service并与之通信
使用startService()启动的service,基本不会与访问者有太多的数据交互,所以访问者与service的数据交互最好是,用bindService()去启动这个service。
Context.bindService(Intent service,ServiceConnection conn,int flags)
Intent service
启动的意图ServiceConnection conn
ServiceConnection一个接口,该对象用于监听访问者与Service之间的状态,当访问者与Service建立连接时,会回调onServiceConnected(ComponentName name, IBinder service)
,当Service发生异常或者其他原因中止时,会回调onServiceDisconnected(ComponentName name)
,但是访问者主动调用unBindService()方法时并回调onServiceDisconnected();int flag
此参考代表是否自动创建Service
MyService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72public class MyService extends Service {
private static final String TAG = MyService.class.getSimpleName();
private MyBinder myBinder=new MyBinder();
//模拟数据
private int serviceData =0;
//是否停止对数据处理
private boolean isStop=false;
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: 开始绑定IBinder");
return myBinder;
}
class MyBinder extends Binder {
public int getDataState(){
return serviceData;
}
public void stop(boolean stop){
isStop=stop;
}
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: 开始创建Service");
new Thread(new Runnable() {
@Override
public void run() {
while (!isStop){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (serviceData>30){
}
serviceData++;
}
stopSelf();
}
}).start();
}
/**
* onStart()方法是Service的早期方法,onStartCommand()是新的推荐方法
* @param intent
* @param flags
* @param startId
* @return
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: 每次调用startService()或者 bindService()方法时,都会回调这个方法");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy: Service开始销毁之前会回调这个方法");
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind: 当Service与之绑定的客户端都断开连接时,会回调这个方法");
return super.onUnbind(intent);
}
}MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//绑定并启动service
findViewById(bindService).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startService(i);
bindService(i,MainActivity.this, BIND_AUTO_CREATE);
}
});
findViewById(R.id.getServiceData).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int dataState = myBinder.getDataState();
Toast.makeText(MainActivity.this,"Service中数据为-->"+dataState, Toast.LENGTH_SHORT).show();
}
});
IntentService
IntentService是继承于Service的,跟Service一样也可以执行耗时任务,IntentService封装了线程和消息循环,IntentService中使用HandlerThread来处理,HandlerThread继承了Thread,内部实现使用了Looper和MessageQueue,用法也很简单。
- HandlerThread
1 | HandlerThread myHandlerThread=new HandlerThread("myHandlerThread"); |
IntentService的源码解析
IntentService封装了HandlerThread,做一个简单分析就可以。
这是IntentService中的一个内部,主要负责异步处理,
onHandleIntent((Intent)msg.obj);
是IntentService是抽象方法,也就是提供给我们实现异步处理的方法,onHandleIntent执行完成后会自动停止Service。
1 | private final class ServiceHandler extends Handler { |
以下代码可以注意HandlerThread的实例化并start,这是service第一次创建时会立即启动一个线程。
1 | @Override |
IntentService的排队处理
我们可以看每次启动Service都会发送一个消息,mServiceHandler.sendMessage(msg);
,熟悉消息机制的我们知道,多余消息会处于等待状态。
1 | //重点这个方法上 |
需要注意的地方
android5.0以上不允许使用隐式意图的方式启动Service
Service是在UI线程中的,所以Service也是不能执行耗时操作的,那么为什么不使用直接在Activity创建线程处理呢?因为如果在Activity退出的情况下,线程执行还未结束,此时所在的进程就变成空进程,系统可能需要内存会优先终止该进程,宿主进程被的终止的话,所在的子线程也会被中止。