深入分析Service启动、绑定过程
Service是Android中一个重要的组件,它没有用户界面,可以运行在后太做一些耗时操作。Service可以被其他组件启动,甚至当用户切换到其他应用时,它仍然可以在后台保存运行。Service 是Android四大组件中与Activity最相似的组件,都代表可执行的程序,区别在于:Service一直运行在后台,没有界面,一旦Service被启动,即完全具有自己的生命周期。
一、创建一个Service
在创建Service时,步骤与Activity很像:
1.继承Service,创建Service子类。
2.在AndroidManifest.xml文件中配置该Service。
下面创建一个最基本的Service组件:
MyService.java
1 public class MyService extends Service { 2 3 //必须实现的方法,用户返回Binder对象 4 @Override 5 public IBinder onBind(Intent intent) { 6 System.out.println("--onBind()--"); 7 return null; 8 } 9 10 //创建Service时调用该方法,只调用一次 11 @Override 12 public void onCreate() { 13 super.onCreate(); 14 System.out.println("--onCreate()--"); 15 } 16 17 //每次启动Servcie时都会调用该方法 18 @Override 19 public int onStartCommand(Intent intent, int flags, int startId) { 20 System.out.println("--onStartCommand()--"); 21 return super.onStartCommand(intent, flags, startId); 22 } 23 24 //解绑Servcie调用该方法 25 @Override 26 public boolean onUnbind(Intent intent) { 27 System.out.println("--onUnbind()--"); 28 return super.onUnbind(intent); 29 } 30 31 //退出或者销毁时调用该方法 32 @Override 33 public void onDestroy() { 34 System.out.println("--onDestroy()--"); 35 super.onDestroy(); 36 } 37 38 }
然后再Manifest.xml文件中红配置一下
1 <service 2 android:name=".MyService"> 3 </service>
为了待会测试的方便,我们在该Service的onCreate()方法里面写一个方法,开启一个线程,让其不断输出“Service运行中”的状态。补充后的MyService类如下:
1 public class MyService extends Service { 2 3 private boolean serviceRunning = false; 4 // 必须实现的方法,用户返回Binder对象 5 @Override 6 public IBinder onBind(Intent intent) { 7 System.out.println("--onBind()--"); 8 return null; 9 } 10 11 // 创建Service时调用该方法,只调用一次 12 @Override 13 public void onCreate() { 14 super.onCreate(); 15 System.out.println("--onCreate()--"); 16 serviceRunning = true; 17 new Thread() { 18 @Override 19 public void run() { 20 while (serviceRunning) { 21 System.out.println("---Service运行中---"); 22 try { 23 sleep(1000); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 } 28 }; 29 }.start(); 30 } 31 32 // 每次启动Servcie时都会调用该方法 33 @Override 34 public int onStartCommand(Intent intent, int flags, int startId) { 35 System.out.println("--onStartCommand()--"); 36 return super.onStartCommand(intent, flags, startId); 37 } 38 39 // 解绑Servcie调用该方法 40 @Override 41 public boolean onUnbind(Intent intent) { 42 System.out.println("--onUnbind()--"); 43 return super.onUnbind(intent); 44 } 45 46 // 退出或者销毁时调用该方法 47 @Override 48 public void onDestroy() { 49 serviceRunning = false; 50 System.out.println("--onDestroy()--"); 51 super.onDestroy(); 52 } 53 54 }
代码分析:首先我们定义一个boolean类型的变量serviceRunning,用来控制新线程中是否输出“---Service运行中---”,通过这样的方式更能让我们直观地看到Servcie的运行状态。
二、启动Service
启动Service和启动一个Activity类似,也是先定义一个Intent让它指向需要启动Service,然后通过调用startService()方法,启动即可,具体代码如下:
1 btn_start_service.setOnClickListener(new OnClickListener() { 2 @Override 3 public void onClick(View arg0) { 4 intent = new Intent(this, MyService.class); 5 startService(intent); 6 } 7 });
代码分析:在主界面中添加了一个按钮,在按钮中首先定义了一个Intent,然后通过startService启动该Intent从而就可以启动Service,与启动一个Activity的方法简直一样啊。
三、停止Service
与启动Service相对应的就是停止Service,通过stopService()即可完成此操作,如下:
1 btn_stop_service.setOnClickListener(new OnClickListener() { 2 @Override 3 public void onClick(View arg0) { 4 stopService(intent); 5 } 6 });
当然,这里Intent需要与startService使用的为一个。
四、绑定Service
绑定Service用是通过调用bindService(Intent service, ServiceConnection conn, int flags)方法来实现的,单看参数就知道与启动Service比起来,会麻烦一些,大体分为如下三步:
第一步:重写onBind()方法,返回Service实例
Service可以让Activity绑定,以获得更加详细的接口。如果先想让一个Service支持绑定,需要实现Service中得onBind()方法,并返回被绑定Service的当前实例,如下:
public IBinder onBind(Intent intent) { System.out.println("--onBind()--"); return new MyBinder(); } public class MyBinder extends Binder{ MyService getService(){ return MyService.this; }
第二步:实现一个ServiceConnection
另外,Service和其他组件的链接表示为一个ServiceConnection,要想一个Service和其他组件绑定,需要实现一个新的ServiceConnection,建立一个链接后,就可以通过重写onServiceConnected()方法和onServiceDisconnected()方法,来获得对Service实例的引用。代码如下:
1 MyService.MyBinder binder = null; 2 class MyServiceConn implements ServiceConnection { 3 // 服务被绑定成功之后执行 4 @Override 5 public void onServiceConnected(ComponentName name, IBinder service) { 6 //service为onBind方法返回的Service实例 7 binder = (MyService.MyBinder) service; 8 } 9 10 // 服务奔溃或者被杀掉执行 11 @Override 12 public void onServiceDisconnected(ComponentName name) { 13 binder = null; 14 } 15 }
第三步:调用bindService执行绑定Service
要想绑定需要给bindService()除了需要给他传递一个需要的Intent和一个ServiceConnection实例外,还需要指定一个标示,如下:
btn_bind_service.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { bindService(intent, myServiceConn, Context.BIND_AUTO_CREATE); } });
其中,myServiceConn为第二步中MyServiceConn实例,Context.BIND_AUTO_CREATE即为标示。
五、解绑Service
解绑Service是通过unbindService实现的,如下:
btn_unbind_service.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if (binder != null) { unbindService(myServiceConn); } } });
这里需要注意的是,unbindService方法中传入的ServiceConnection实例一定要跟绑定时的一致,否则可能会导致程序崩溃。
六、试验
主界面简单,只有四个按钮,如下:
1、当按下startService按钮,然后再按下stopService按钮时,日志如下:
2、当按下bindService,然后再按下unbindService时,日志如下:
3、当按下startService接着按bindService时,这时候就需要unbindService和stopService都按下后才能停止Service,日志如下:
七、总结
1、启动Service和停止Service是一一对应的,绑定Service和解绑Servcie是一一对应的,如果同时启动和绑定了Service,必须通过解绑和停止Service才能使该Service真正停止。
2、应用组件(客户端)可以调用bindService()绑定到一个service.Android系统之后调用service的onBind()方法,它返回一个用来与service交互的IBinder.绑定是异步的.bindService()会立即返回,它不会返回IBinder给客户端.要接收IBinder,客户端必须创建一个ServiceConnection的实例并传给bindService().ServiceConnection包含一个回调方法,系统调用这个方法来传递要返回的IBinder.
声明:欢迎转载,转载时请注明本文链接。
作者:CodingBlock
出处:http://www.cnblogs.com/codingblock/
本文版权归作者和共博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如果文中有什么错误,欢迎指出。以免更多的人被误导。