Android系统中默默的劳动者—-Service在系统中扮演了一个很重要的角色,解决了实现程序后台运行的问题,这使得应用程序即使在关闭的情况下,也可以在后台继续执行一些后台任务。
1.Service的适用场景
Service是没有界面的,所以适用于不需要和用户交互而且要长期运行的任务,比如:QQ在关闭后仍然需要一个后台程序一直监听是否有收到消息,如果有就用将消息传递到Notification,在通知栏提示有新消息。
2.Service的注意要点
(1)服务的运行不依赖任何用户界面,即使当程序被切换到后台,或者用户打开了另一个应用程序,服务仍然能够保持正常运行。
(2)服务并不是运行在一个独立的进程中,而是依赖于创建服务时所在的应用程序进程。当某个应用程序被杀死时,所有依赖于该进程的服务都会被停止运行。
(3)虽然Service是在后台执行的,但Service并不会自动开启一个子线程去执行耗时操作,而是默认在主线程中执行。这就需要我们在自定义的Service内部开启子线程执行具体的任务(下面会有代码举例做法)。否则直接在主线程中执行耗时操作,容易引起主线程阻塞,导致ANR异常。
(4)每个被创建的服务都是单例的,一个服务一旦被启动或者被绑定了之后,就会一直处于运行状态,只有当stopService()和unbindService()同时被调用,服务才会被销毁。
(5)只有activities,services,和contentproviders可以绑定到一个service—你不能从一个broadcastreceiver绑定到service。
3.Service的生命周期及使用方法
上图是官方给出的Service生命周期方法的回调回程,每一个回调方法都代表了一个具体的Service状态。也可以看出根据启动方式分类可以分为两类:startServie()启动的Service(未和Activity绑定的Service)和bound Service(和Activity绑定的Service).
下面总结每个生命周期方法时的特点:
(1)onCreate():第一次创建服务时被回调,如果服务已经被创建过了就不再回调此方法。
(2)onStartCommand():调用了Context的startService()方法,服务就会被启动,onStartCommand()就会被回调,所以这个回调方法是服务被启动时被系统回调的。启动之后会一直保持运行状态,直到stopService()或者stopSelf().并且每个服务只会存在一个实例,就像Activity的singleInstance(全局单例)模式一样.
初次创建:onCreate()–>onStartCommand()–>onStart()
已经创建过:onStartCommand()–>onStart()
通常在此方法中编写逻辑代码。
(3)onBind():调用Context的bindService()能获取一个服务的持久连接,这时会回调onBind()方法,如果此服务还未被创建:则onCreate()–>onBind()
(4)onDestroy():服务被销毁时回调,也就是当调用了stopService()方法,onDestroy()会被执行。
那么绑定的Service当执行了unbandService()之后也会回调onDestroy().
问题:如果一个服务显示被startService()方式启动,后又调用bindService(),这种情况如何销毁服务呢?
很简单,先取消绑定(unbindService()),再关闭该服务(stopService()或stopSelf())。
具体实现代码举例如下(布局文件略):
Myservice.java:
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
final String TAG = "MyService-->";
MyBinder myBinder;
public MyService() {
Log.d(TAG, "MyService: ");
}
//当一个活动和服务绑定后就可以调用该服务的Binder提供的方法了
class MyBinder extends Binder {
public void startOperate() {
Log.d(TAG, "startOperate: -->");
}
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: ");
//throw new UnsupportedOperationException("Not yet implemented");
return myBinder;
}
@Override
public void onStart(Intent intent, int startId) {
Log.d(TAG, "onStart: ");
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy: ");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
Log.d(TAG, "onRebind: ");
super.onRebind(intent);
}
}
MainActivity.java:
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import static android.R.attr.onClick;
public class MainActivity extends AppCompatActivity {
final String TAG = this.getClass().getSimpleName();
MyService.MyBinder myBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected: ");
//Binder implements IBinder
myBinder = (MyService.MyBinder) service;
myBinder.startOperate();
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected: ");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.start:
Intent intent = new Intent(this, MyService.class);
startService(intent);
break;
case R.id.stop:
Intent intent1 = new Intent(this, MyService.class);
stopService(intent1);
break;
case R.id.bind_service:
Intent bindService = new Intent(this, MyService.class);
/*第一第二参数很好理解,第三个参数是一个标志,它表明绑定中的操作.它一般应是BIND_AUTO_CREATE,这样就会在service不存在时创建一个.其它可选的值是BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,不想指定时设为0即可*/
bindService(bindService, connection, BIND_AUTO_CREATE);
break;
case R.id.unbind_service:
unbindService(connection);
break;
}
}
}
4.IntentService的使用及与Service的差异
Service作为后台服务的实现者,虽然是解决程序后台运行的问题,但是也是有不足需要补充的。比如没有向AsyncTask类似的异步操作方法,需要手动在onStartCommand()方法中开启新的线程执行耗时任务。还有就是在任务执行完毕后没有提供自动关闭的机制,需要手动去关闭。
基于上述的不足,IntentService对Service做了很好的补充,IntentService继承于Service,官方介绍如下:
可以看出IntentService和Service的不同:
(1)能处理异步请求;
(2)开启新的工作线程完成耗时操作;
(3)在操作完成后自动stop。
下面列举IntentService的使用:
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
/**
* created by zhiyuan at 2017/3/8
*/
public class MyIntentService extends IntentService {
final String TAG = MyIntentService.class.getSimpleName();
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public MyIntentService() {
super("MyIntentService");
}
//子线程中执行
@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent: current thread-->" + Thread.currentThread().getId());
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
}
}
运行结果: