service基础总结
最近在学习service,网上看了很多的资料,于是想着总结一下,以后方便查阅。说明一下本 文中的内容,图片可能来自其他地方,都是自己觉得很好便拿来主义,站在巨人的肩膀上学习。下面附上原文链接和自己觉得不错的文章,各取所求!!
来自Carson_Ho的:一份全面 & 简洁的 Service 知识讲解攻略
基础总结篇之四:Service完全解析
郭神的service解析
下面我们分如下几个点来学习下service
- service简介
- 生命周期
- service分类
- 使用方法
- 其他
service简介
service可以说是一个在后台运行的Activity,它不是一个单独的进程,而是运行在他的宿主进程的主线程中。它用于处理一些不干扰用户使用的后台耗时操作或者去执行某些需要长期运行的任务,如下载,网络获取,播放音乐等,必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态。他可以通过INTENT来开启,同时也可以绑定到宿主对象(调用者例如acticity上)来使用,通过Context.startService()和Context.bindService()两种方式开始工作。
service生命周期
- 官方说明图
可以看到Service生命周期可以从两种启动Service的模式开始讲起,分别是context.startService()和context.bindService()。
(1).startService的启动模式下的生命周期(此方式不可操作服务):当我们首次使用startService()启动一个服务时,系统会实例化一个Service实例,依次调用其onCreate(创建)和onStartCommand(开始)方法,然后进入运行状态,此后,如果再使用startService启动同一服务时,不再创建新的服务对象(不调用onCreat()方法),而是直接调用onStartCommand()方法;如果我们想要停掉一个服务,可使用stopService()方法,此时onDestroy方法会被调用,需要注意的是,不管前面使用了多个次startService,只需一次stopService,即可停掉服务。
(2).bindService启动模式下的生命周期:在这种模式下,当调用者首次使用bindService()绑定一个服务时,系统会实例化一个Service实例,并一次调用其onCreate方法和onBind方法,然后调用者就可以和服务进行交互了,此后,如果再次使用bindService()绑定服务,系统不会创建新的Service实例,也不会再调用onBind方法;如果我们需要解除与这个服务的绑定,可使用unbindService()方法,此时onUnbind方法和onDestroy方法会被调用。
两种模式不同之处:startService模式下调用者与服务无必然联系,即使调用者结束了自己的生命周期,只要没有使用stopService方法停止这个服务,服务仍会运行;通常情况下,bindService模式下服务是与调用者生死与共的,在绑定结束之后,一旦调用者被销毁,服务也就立即终止,就像江湖上的一句话:不求同生,但愿同死。
- 手动调用方法具体介绍
手动调用方法 | 作用 |
---|---|
startService() | 启动服务 |
stopService() | 关闭服务 |
bindService() | 绑定服务 |
unbindService() | 解绑服务 |
内部自动调用的方法 | 作用 |
---|---|
onCreat() | 创建服务 |
onStartCommand() | 开始服务 |
onDestroy() | 销毁服务 |
onBind() | 绑定服务 |
onUnbind() | 解绑服务 |
具体介绍
- 常见生命周期应用场景
service分类
6种类型如下:
各类型特点
使用方式
- startService()使用
1.创建服务类
public class MyService extends Service {}
并重写
@Override
public void onCreate() {
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//接受传递过来的intent的数据等
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
}
2.在AndroidMainfest.xml文件中配置注册该Service
<service android:name="服务类所在的包名.MyService" />
3.启动服务
Intent intent = new Intent(getApplicationContext(), MyService.class);
startService(intent);
4.销毁服务
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
- bindService()启动的使用方式
1.创建服务类,重写onBind()
public class MyService extends Service {
public static final String TAG = "MyService";
private MyBinder mBinder = new MyBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
class MyBinder extends Binder {
public void startDownload() {
// 执行具体的下载任务
}
}
}
2.在AndroidMainfest.xml文件中配置注册该Service.如上。
3.启动服务:
在Activity中添加
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
//服务绑定失败时的操作
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyService.MyBinder) service;
myBinder.startDownload();
//服务绑定成功时的操作 在这里可以调用MyService中的MyBinder里的piblic方法
}
};
绑定服务
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent,connection, int flags)
4.销毁服务
unbindService(connection);
注:
1: flag参数含义如下:
1).Context.BIND_AUTO_CREATE
说明:表示收到绑定请求的时候,如果服务尚未创建,则即刻创建,在系统内存不足需要先摧毁优先级组件来释放内存,且只有驻留该服务的进程成为被摧毁对象时,服务才被摧毁
2).Context.BIND_DEBUG_UNBIND
说明:通常用于调试场景中判断绑定的服务是否正确,但容易引起内存泄漏,因此非调试目的的时候不建议使用
3).Context.BIND_NOT_FOREGROUND
说明:表示系统将阻止驻留该服务的进程具有前台优先级,仅在后台运行,该标志位位于Froyo中引入。
2:当acticity中既含有bindService又含有startService时服务销毁要注意 unbindService(connection)和stopService(stopIntent)要一起调用,即一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。
其他
service与thread关系
service与thread没有必然联系,提到service必提到后台,其实后台就是指,它的运行是完全不依赖UI的。即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行。我们知道service运行在主线程中,但是怎么执行耗时操作呢,这里我们就可以在Service中再创建一个子线程,然后在子线程中去处理耗时逻辑就没问题了
那为什么不直接在Activity里创建呢?这是因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况.
比较标准的Service就可以写成:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
// 开始执行后台任务
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
class MyBinder extends Binder {
public void startDownload() {
new Thread(new Runnable() {
@Override
public void run() {
// 执行具体的下载任务
}
}).start();
}
}