1、结论
1.通过startservice开启的服务.一旦服务开启, 这个服务和开启他的调用者之间就没有任何的关系了.
调用者不可以访问 service里面的方法. 调用者如果被系统回收了或者调用了ondestroy方法, service还会继续存在
2.通过bindService开启的服务,服务开启之后,调用者和服务之间 还存在着联系 ,
一旦调用者挂掉了.service也会跟着挂掉 .
2、生命周期
startService: onCreate -> onStartCommand -> onDestory ,在多次调用startService的时候,onCreate不重复执行,但是onStartCommand会执行。startService调用了这后,会一直存在,直到其调用了stopService。
bindService : onCreate -> onBind -> onUnbind -> onDestory,多次调用bindService,onCreate及onBind都只执行一次。它生命周期跟随其调用者,调用者释放的时候,必须对该Service解绑,当所有绑定全部取消后,系统即会销毁该服务。 bindService 的方式通过onServiceConnected方法,获取到Service对象,通过该对象可以直接操作到Service内部的方法,从而实现的Service 与调用者之间的交互。
3、使用场景
如果想要启动一个后台服务长期进行某项任务,那么使用startService
如果只是短暂的使用,那么使用bindService。
如果想启动一个后台服务长期进行任务,且这个过程中需要与调用者进行交互,那么可以两者同时使用,或者使用startService + BoardCast/ EventBus 等方法。
对于既使用startService,又使用bindService的情况,结束服务时需要注意的事项:
Service的终止,需要unbindService和stopService都调用才行;
顺便提一下IntentService,与Service的区别在于它内部封装了一个工作线程,也就是说,在其内部onHandleIntent的代码都是在子线程里面工作的。
4、示例代码
目的:使用Service播放音乐
public class PlayerServicePresenter extends BasePresenter<IPlayerServiceContract.Iview> implements IPlayerServiceContract.IPresenter{
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//IOC 数据回调 和Service链接成功后 调用
PlayerService.PlayerBinder binder = (PlayerService.PlayerBinder) service;
playerService = binder.getService();
playOrPaused();
}
@Override
public void onServiceDisconnected(ComponentName name) {
//和Service链接断开后 调用
if (playerService != null) {
playerService.unbindService(mConnection);
playerService = null;
}
}
};
private PlayerService playerService;
public PlayerServicePresenter(IPlayerServiceContract.Iview view) {
super(view);
}
@Override
public void bindService(Context context) {
if (playerService != null) {
playOrPaused();
} else {
Intent intent = new Intent(context, PlayerService.class);
context.bindService(intent, mConnection, Service.BIND_AUTO_CREATE);
}
}
@Override
public void playOrPaused() {
if (playerService != null) {
//开启播放音乐
playerService.playOrPause(new RawPlayerSource().setPath(ContextHelper.getInstance().getApplicationContext().getPackageName(), R.raw.minyao),ContextHelper.getInstance().getApplicationContext());
}
}
}
public class PlayerService extends Service implements IPlayerListener {
private PlayerState mState = PlayerState.IDLE;
private IPlayer mPlayer;
private PlayerFactory mPlayerFactory;
@Override
public void playerStateChanged(PlayerState state) {
this.mState = state;
}
public class PlayerBinder extends Binder {
public PlayerService getService() {
return PlayerService.this;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new PlayerBinder();
}
// onStartCommand 在 startService 有作用,start多次就会调用多次,一般用来给Serivice传递数据
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
//onCreate 不管 start 还是 bind 也不管调用几次,只会启动一次,常用来做全局初始化操作
@Override
public void onCreate() {
super.onCreate();
}
public void playOrPause(IPlayerSource playerSource,Context mContext) {
switch (mState) {
case IDLE:
//初始化播放器 去播放
if (mPlayer != null) {
mPlayer.release();
}
if (mPlayerFactory == null) {
mPlayerFactory = new PlayerFactory();
}
if (mPlayer == null) {
mPlayer = mPlayerFactory.createPlayer(mContext);
}
if (mPlayer == null) {
//播放器创建失败
return;
}
//拿到播放器 去播放
mPlayer.setPlayingListener(this);
mPlayer.prepare(mContext,playerSource);
break;
case STARTED:
//去暂停
if (mPlayer != null) {
mPlayer.paused();
}
break;
case PAUSED:
//继续播放
if (mPlayer != null) {
mPlayer.reStart();
}
break;
case PREPARING:
break;
default:
break;
}
}