Service是Android实现程序后台任务的解决方案,非常适合处理一些不需要与用户交互但又要长期运行的任务。但不要被它的“后台”二字所欺骗,Service默认并不是运行在子线程中的,他同样和Activity一样运行在UI线程。所以需要在Service中执行耗时操作时,必须创建一个子线程来完成。
1. Service生命周期
Service的生命周期比Activity来说简单得多,只有3个,分别是onCreate,onStartCommand,onDestroy。一旦通过startService()方法启动服务后,首次创建服务会调用onCreate()方法,然后调用onStartCommand()方法。每次调用startService()方法,onStartCommand()方法都会执行,每个服务都只会存在一个实例,不管你调用多少次startService()。
启动服务后,服务会一直保持运行状态,直到stopService()和stopSelf()函数被调用。服务停止时,onDestroy()方法会被调用,至此,Service的整个生命周期就走完了。
一个简单的Service:
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService", "onCreate executed");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService", "onStartCommand executed");
new Thread(new Runnable() {
@Override
public void run() {
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d("MyService", "onDestroy executed");
super.onDestroy();
}
}
2. 绑定服务
绑定服务可以让Activity和Service的关系更密切一些,这就需要用到Service中唯一的一个抽象方法onBind(),在上面的代码中也可以看到,onBind()方法返回的是一个Binder实例。下面通过一个简单的下载功能来理解Activity是如何和Service绑定的,实现这个功能的思路是创建一个专门的Binder对象来对下载功能进行管理
public class MyService extends Service {
private DownloadBinder mBinder = new DownloadBinder();
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService", "onCreate executed");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService", "onStartCommand executed");
new Thread(new Runnable() {
@Override
public void run() {
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d("MyService", "onDestroy executed");
super.onDestroy();
}
class DownloadBinder extends Binder {
public void startDownload(){
Log.d("MyService", "startDownload executed");
}
public int getProgress(){
Log.d("MyService", "getProgress executed");
return 0;
}
}
}
对上面的Service类进行改动,我们创建了一个DownloadBinder类,接着在MyService中创建DownloadBinder实例,通过onBind()方法返回。
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private MyService.DownloadBinder downloadBinder;
private ThreadLocal<Integer> mThreadLocal = new ThreadLocal<>();
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (MyService.DownloadBinder) service;
downloadBinder.startDownload();
downloadBinder.getProgress();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bindService = findViewById(R.id.bind_service);
Button unbindService = findViewById(R.id.unbind_service);
bindService.setOnClickListener(this);
unbindService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.bind_service:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
break;
case R.id.unbind_service:
unbindService(connection);
break;
}
}
}
接着我们在Activity中创建一个ServiceConnection的匿名类,重写里面的两个方法,onServiceConnected()会在活动与服务成功绑定时调用,onServiceDisconnected()会在活动与服务解绑时调用。其中,onServiceConnected()参数中的IBinder就是我们服务中onBind()方法所返回的DownloadBinder ,至此我们的下载功能就完成了。
3. IntentService
在前面我们说到,Service并不是默认运行在子线程中的,所以,google提供了一个IntentService来完成这样的操作。IntentService将用户的请求执行在一个子线程中,我们只需要重写onHandleIntent()方法,在这个方法里面去处理一些耗时操作。任务执行完毕后,IntentService会调用stopSelf自我销毁
一个简单的IntentService:
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d("MyIntentService", "This is " + Thread.currentThread().getId());
}
@Override
public void onDestroy(){
super.onDestroy();
Log.d("MyIntentService", "onDestroy executed");
}
}