Service(服务)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。Service的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,Service仍然能够正常运行。
Service并不是运行在一个独立的进程当中,而是依赖于创建Service时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的Service也会停止运行。
Service不会自动开启线程,所有的代码都是默认运行在主线程当中的。我们需要在Service的内部手动创建子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞的情况。
1.定义一个Service
利用AndroidStudio创建一个Service。其中Exported属性表示是否允许除了当前程序之外的其他程序访问这个Service,Enabled属性表示是否启用这个Service。
public class MyService extends Service {
public MyService() {
}
/**
* 在Service创建时调用
*/
@Override
public void onCreate() {
super.onCreate();
}
/**
* 在每次Service启动时调用
* 如果希望Service一旦启动就立刻去执行某个动作,可以将逻辑写在这里
* @param intent
* @param flags
* @param startId
* @return
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
/**
* 在Service销毁时调用
*/
@Override
public void onDestroy() {
super.onDestroy();
}
/**
* 必须要在子类中实现的方法
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
接下来在AndroidMainfest.xml文件中注册Service后,便可以开始使用。
2.启动和停止Service
构建Intent对象,然后利用Context.startService()和Context.stopService()便可以进行相应的启动和停止。在Service的任何一个位置调用stopSelf(),也可以让这个Service停下。
public class ServiceActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service);
Intent intent = new Intent(this, MyService.class);
startService(intent);
stopService(intent);
}
}
public class MyService extends Service {
/**
* 在每次Service启动时调用
* 如果希望Service一旦启动就立刻去执行某个动作,可以将逻辑写在这里
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Service中任意位置调用stopSelf(),可停止Service;
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
}
3.Service和Activity进行通信
要实现Service和Activity通信,需要将两者进行绑定。首先在Service中定义一个Binder类,并于onBind()方法中返回。用于当成功绑定时返回给Activity进行相关操作。
public class MyService extends Service {
private DownloadBinder mBinder;
/**
* 在Service创建时调用
*/
@Override
public void onCreate() {
mBinder = new DownloadBinder();
super.onCreate();
}
/**
* 必须要在子类中实现的方法
* @param intent
* @return 返回mBinder给Activity
*/
@Override
public IBinder onBind(Intent intent) {
// 返回mBinder给Activity
return mBinder;
}
class DownloadBinder extends Binder {
public void startDownload() {
}
public int getProgress() {
return 0;
}
}
}
接下来,在Activity创建ServiceConnection的匿名类实例,并重写onServiceConnected()和onServiceDisconnected()方法,这两个方法分别在Activity与Service成功绑定、Activity与Service连接断开时调用。
通过onServiceConnected()方法可以获得在Service.onBind()中返回的Binder,从而控制Service进行一系列操作,达到Activity指挥Service的效果。
public class ServiceActivity extends AppCompatActivity {
private MyService.DownloadBinder mBinder;
//初始化ServiceConnection
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获得Service.mBinder,从而操控Service
mBinder = (MyService.DownloadBinder) service;
mBinder.startDownload();
mBinder.getProgress();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service);
Intent intent = new Intent(this, MyService.class);
//进行绑定,BIND_AUTO_CREATE表示在Activity和Service进行绑定后,自动创建Service
bindService(intent, mConnection, BIND_AUTO_CREATE);
//解绑
unbindService(mConnection);
}
}
4.Service生命周期
生命周期方法大致包括onCreate()、onStartCommand()、onBind()、onDestroy()等方法。
当调用Context.startService()方法,相应的Service就会启动起来并回调onStartCommand()方法。如果这个Service之前没有创建过,则onCreate()方法先于onStartCommand()方法执行。虽然每调用一次startService()方法,onStartCommand()就会执行一次,但实际上每个Service只会存在一个实例。
当调用Context.bindService()来获取一个Service的持久连接,这时就会回调Service中的onBind()方法。如果这个Service之前没有被创建过,onCreate()会先于onBind()执行。
当调用了startService()后,再去调用stopService(),这时Service中的onDestroy()就会执行。类似地,当调用了bindService()后,再去调用unbindService(),onDestroy()也会执行。
但是,当startService()和bindService()都被调用了,根据Android机制,需要调用stopService()和unbindService(),onDestroy()才会被调用。
网友评论