服务(Service)是Android中实现程序后台运行的解决方案,他非常适合去执行那些不需要和用户交互,而且还需要长期执行的任务。服务的运行不依赖任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。不过需要注意的一点是,服务不是运行在一个独立的进程当中的,而是依赖创建服务时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。
定义一个服务:
public class MyService extends Service {
private static final String TAG = "MyService";
@Override
public void onCreate() {
super.onCreate();
//在服务创建的时候调用
Log.d(TAG, "onCreate: ");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
//在每次启动服务的时候调用
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: ");
//在绑定服务的时候调用
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
}
}
并且需要在AndroidManifest.xml文件中进行注册MyService类。
启动服务有两种方式,其中第一种是:
1、startService()
Intent mService = new Intent(this,MyService.class);
startService(mService);
其执行的生命周期是
onCreate()->onStartCommand()
停止服务的方法,一种是外部控制:(外部告诉Service该停止了)
stopService(mService);
一种是内部停止:(Service内部自己控制停止服务)
stopSelf()
如果多次调用startService()方法,onCreate()方法只会在第一次调用时执行,因此第一次服务还未被创建,但后续的调用onCreate()不会再执行,只会执行onStartCommand()方法。就算是多次执行startService()方法,也只会产生一个Service实例,因此只需要调用一次stopService()或者stopSelf()方法就可以停止服务了。
2、bindService()
启动服务的另外一种方式是绑定服务,由上面的启动方式可以看出,startService()只告诉了Service可以启动了,后续的任务完全由Service控制,这样活动和服务之间并没有什么通信,如果我们想要控制Service,想要和Service通信,那么就可以使用绑定服务的方式去开启。
//自定义Binder内部类,并通过onBind返回该对象
private MyBinder binder = new MyBinder();
public class MyBinder extends Binder {
public void startDownload(){
}
public void getProgress(){
}
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: ");
//在绑定服务的时候调用
return binder;
}
在活动中使用如下:
private MyService.MyBinder myBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//活动与服务绑定时调用
myBinder = (MyService.MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
//活动与服务断开时调用
}
};
Intent mService = new Intent(this,MyService.class);
//BIND_AUTO_CREATE表示活动与服务绑定之后自动创建服务
bindService(mService,connection,BIND_AUTO_CREATE);
其生命周期如下:
onCreate()->onBind()
就算是多次点击绑定服务,onBind方法和onCreate都只会调用一次,只需要调用一次unbindService就可以解绑服务了。
unbindService(connection);
另外需要注意的是,任何一个服务在整个应用程序范围内都是通用的,即MyService可以和MainActivity绑定,也可以和其他活动进行绑定,而且在绑定完成后获取到的是相同的MyBinder实例。
如果一个服务既调用了startService又调用了bindService,那么这种情况下该如何让服务停止销毁呢?根据Android系统的机制,一个服务只要被启动或者被绑定之后,就会一直处于运行状态,必须要让上述两个条件同时不满足,服务才能被销毁。即需要同时调用stopService和unbindService服务才会销毁。
3、IntentService
这个类是为了解决Service不能主动创建子线程、不能自动停止而提供的一个类,这个类很好的解决了上面的两种问题,可以实现异步,自动停止的服务。
这是一个抽象类,需要自定义一个IntentService类:
public class MyIntentService extends IntentService {
private static final String TAG = "MyIntentService";
public MyIntentService() {
//提供一个无参的构造函数,内部必须调用父类的有参构造函数
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//该方法在子线程中运行
Log.d(TAG, "onHandleIntent: "+Thread.currentThread().getId());
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
}
}
其中开启IntentService类的方式:
//对比IntentService中的onHandleIntent方法的线程
Log.d(TAG, "buttonClick: "+Thread.currentThread().getId());
Intent intentService = new Intent(this,MyIntentService.class);
startService(intentService);
其运行结果是:
myapplication D/MainActivity: buttonClick: 2
myapplication D/MyIntentService: onHandleIntent: 1304
myapplication D/MyIntentService: onDestroy:
可以看出IntentService确实实现了异步,自动结束的功能。