上次我们留下一个疑问,其实问题的答案很简单,就是Service只在第一建立时才会创建onCreate()方法,一旦Service已经建立成功,当程序再次调用时不在执行onCreate()方法,而直接执行onStartCommand(),也就是说onStartCommand()可以不止一次被调用。顺带说一句public int onStartCommand(Intent intent, int flags, int startId)这个方法有个参数startId,这个就是代表service运行的次数,换句话理解就是执行一次onStartCommand()这个数就会自动加1。
下面总结一下,Service的绑定使用。
1. 首先还是建立一个Service,Service的建立请参阅上一篇文章,这里就不在赘述了。
不过这里onBind()方法不再返回一个空,而是返回一个Ibinder的接口给调用的接口。
public IBinder onBind(Intent intent) {
Log.d("zinc",">>>>>>>>>service is onbind<<<<<<<<<<<<");
// TODO Auto-generated method stub
return new MyBinder();
}
在建立一个内部类MyBinder()继承Binder
public class MyBinder extends Binder {
public MyService getMyService() {
return MyService.this;
}
}
2. 在需要的Context中建立SerivceConnect接口,这里我用一个activity和service进行绑定。activity的完整代码如下:
public class BindServiceTestActivity extends Activity implements OnClickListener {private Button startButton;
private Button stopButton;
private MyService myService;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startButton= (Button)findViewById(R.id.startbutton);
stopButton= (Button)findViewById(R.id.stopbutton);
startButton.setOnClickListener(this);
stopButton.setOnClickListener(this);
}
public void onClick(View v) {
switch(v.getId()){
case R.id.startbutton:
Intent intent = new Intent();
intent.setClass(this, MyService.class);
bindService(intent,conn,Service.BIND_AUTO_CREATE);
break;
case R.id.stopbutton:
unbindService(conn);
break;
default:
break;
}
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
myService = null;
}
private ServiceConnection conn = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
Log.d("zinc",">>>>>>>>>>>>service has already bind with activity<<<<<<<<<<<");
myService = ((MyService.MyBinder)service).getMyService();
//如果myService不为null,去执行service中的justest()方法;
Log.d("zinc",">>>>>>>>>>myService is not null<<<<<<<<");
myService.justTest();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
Log.d("zinc",">>>>>>>>>>>>service has already unbind with activity<<<<<<<<<<<");
}
};
}
onServiceConnected(ComponentName name, IBinder service) 这个方法是context绑定service后会回调到这里,所以我们打个log看看activity有没有和service绑定成功。
蓝色字体的一行表示返回的IBinder类型转换,再去获取MyService的实例。再给出Service的代码这样就一目了然了:
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
Log.d("zinc",">>>>>>>>>service is onbind<<<<<<<<<<<<");
// TODO Auto-generated method stub
return new MyBinder();
}
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return super.onUnbind(intent);
}
public class MyBinder extends Binder {
public MyService getMyService() {
return MyService.this;
}
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.d("zinc",">>>>>>>>>>service onCreate()<<<<<<<<<<<<");
Toast.makeText(MyService.this, "服务已建立", Toast.LENGTH_LONG).show();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.d("zinc",">>>>>>>>>>service onStartCommand()<<<<<<<<<<<<<");
Toast.makeText(MyService.this, "服务已启动", Toast.LENGTH_LONG).show();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d("zinc",">>>>>>>>>>service onDestory()<<<<<<<<<<<<");
Toast.makeText(MyService.this, "服务已停止", Toast.LENGTH_LONG).show();
}
public void justTest(){
Log.d("zinc",">>>>>>>>>justTest()<<<<<<<<<<");
}
}
有兴趣的朋友可以把程序调试一遍,你会发现:绑定service后,不会执行service的onStartCommand() 方法,只会执行onCreat()方法;当然可以用startService去启动Service。
最后有一点也很重要:红色字体的一行,当activity销毁时,记得把myService这个引用重新赋值为null;我也是听了陈老师的话才有点明白。因为myService实际上是MyService的一个内部类MyBinder获取的引用,如果myService最后在activity中不处理为null的话,那这个引用始终释放不了,最终Service无法真正的释放。虽然从log总看到service好像走到onDestroy,但是因为内部引用始终占据内存空间,java的回收机制不会去处理外部类的回收。