首先来看一下启动服务的两种方式startService和bindService:ide
StartService(Intent intent)spa
start的方式只能简单的开启服务,而且开启以后基本不能勇于服务的运行逻辑,话句话说,开启后服务就和开启服务的线程没什么关系了。可是一般咱们都是更加紧密的去联系服务,可能会获取一些运行的结果,好比执行结果,进度信息等,那就须要使用bind的方式开启服务了线程
bindService地方法就比较丰富,其传入三处有三个,类型分别为代理
Intent,ServiceConnection,Int. 其中第一个就不细说了,意图你们都明白,第二个为接口,其中包含两个必须实现的方法: onServiceConnected(ComponentName var1, IBinder var2) 表明服务链接,第一个参数暂且不提,第二个先记住它叫Ibindr,后面会提到。 onServiceDisconnected(ComponentName var1) 表明与服务失去链接 第三个参数Int类型就是服务执行的模式。
虽然BindService参数丰富,功能强大,可是其使用逻辑也略微复杂,下面慢慢道来。code
采用bind的方法绑定开启服务component
a>先new一个类实现ServiceConnection接口,这个类用于为bind方法的第二个是参数作准备,我理解是定义与服务的链接通道。对象
private class MyConn implements ServiceConnection{ //通道成功链接 @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { //此处IService表明在Service中提供一个调用其内部方法的接口,为接口类型 mybinder= (IService) iBinder; Log.d("phone.....","3. 见到服务的代理对象:"+mybinder.toString()); } //通道失去链接 @Override public void onServiceDisconnected(ComponentName componentName) { } }
b>实例化出通道,而后使用执行bind方法。blog
在外部类: private MyConn comm; 内部方法: comm=new MyConn(); bindService(intent,comm, Context.BIND_AUTO_CREATE); 其中Context.BIND_AUTO_CREATE表明若服务不存在实例则建立实例
服务内部实现一个代理人类,这个代理继承自Ibinder,也就是上文ServiceConnection中的onServiceConnected方法的一个返回值,这个Ibinder对象就是服务中的代理在阜外外部的一个引用,经过这个引用就能够调用Ibinder实现的接口中的方法。继承
private class Mybinder extends Binder implements IService{ //由代理去调用服务内部的方法 public void callinService(){ Log.d("phone.....","5. 代理人执行了服务里的方法"); @Override callInService(); } }
定义IService的接口接口
这个接口就是上文提到的IService接口,这个接口中一般定义想要暴露给外部的方法,外部也只能看到IBinder中实现的这个接口的方法,除非你将上一节中的MyBinder这个类定义为Public。
public interface IService { public void callInService(); }
返回代理人对象
具体服务是如何将IBinder的引用返回给外部呢,就是经过Service惟一的必须实现的方法:
@Nullable @Override public IBinder onBind(Intent intent) { //当有需求时,呼叫代理人去接待 Mybinder mybinder=new Mybinder(); Log.d("phone.....","2. 成功绑定,返回服务的代理对象:"+mybinder.toString()); return mybinder; }
实现serviceConnection接口里面的方法
如今你就能够在通道中看到Service的代理对象了:
private class MyConn implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { myBinder = (IService) service; System.out.println("Activity,获得代理人对象"); }
调用接口里面的方法
经过MyBinder这个Service的代理对象,就能够执行服务中对外开放的方法了。固然这个方法就须要你本身去定义了。
mybinder.callInService();
最后的最后,大体说明一下两种方式开启服务的特色
生命周期
oncreate()--->onstartcommand()--->onstart()--->onDestroy()
能够屡次调用,不会重复建立,oncreate()只会执行一次
以start方式开启的服务也只能中止一次,屡次调用stopservice()是无效的
以start方式开启的服务与UI线程失去关系,即便UI线程被销毁,服务仍然能够正常运行
不能调用服务中的方法
生命周期
oncreate() --->onbind() -->onunbind()---->ondestry();
只能成功绑定和解绑一次
与绑定的UI线程同时被销毁(一根绳上的蚂蚱^_^)
能够调用服务中的方法
既然start开启的服务不能调用方法,bind方式开启的服务生命力又很弱,那么可否两种方式的有点么?答案固然是确定的,不然服务的应用能力就太弱了。
经过startService()方式开启服务(只能经过调用stopService中止)
经过bindService进行绑定,以进行服务的方法调用(当须要的时候)
经过unbindService进行解绑(不须要调用方法了,在UI线程被销毁以前解绑)
经过stopService中止服务
这样咱们就能够灵活的使用Service,当须要的时候能够随时进行调用,不要的时候又能够长期运行于后台而不用保留UI线程。这也是服务最多见的用法。