服务绑定与解绑
通过服务的绑定与解绑也可以实现类似服务启动与停止的功能,通过查看全国的实时数据,则实现如:
activity_main.xml:
xml version="1.0"encoding="utf-8"?>
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开启服务"/>
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="关闭服务"/>
android:id="@+id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="绑定服务"/>
android:id="@+id/button4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="解除绑定服务"/>
MainActivity.java:
packagecom.exle.servicelifecycle;
importandroidx.appcompat.app.AppCompatActivity;
importandroid.content.ComponentName;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.content.ServiceConnection;
importandroid.os.Bundle;
importandroid.os.IBinder;
importandroid.view.View;
importandroid.widget.Button;
public classMainActivityextendsAppCompatActivityimplementsView.OnClickListener{
Buttonbt_start;
Buttonbt_stop;
Buttonbt_bind_service;//绑定服务
Buttonbt_unbind_service;//解除绑定服务
Intentintent;
MyConnconn;
@Override
protected voidonCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_start= (Button)this.findViewById(R.id.button);
bt_stop= (Button)this.findViewById(R.id.button2);
bt_bind_service= (Button)this.findViewById(R.id.button3);
bt_unbind_service= (Button)this.findViewById(R.id.button4);
bt_start.setOnClickListener(this);
bt_stop.setOnClickListener(this);
bt_bind_service.setOnClickListener(this);
bt_unbind_service.setOnClickListener(this);
//自定义MyService实现服务意图
intent=newIntent(this,MyService.class);
conn=newMyConn();
}
@Override
public voidonClick(Viewv) {
switch(v.getId()) {
caseR.id.button://开启服务
startService(intent);
break;
caseR.id.button2://停止服务
stopService(intent);
System.out.println("服务click button2");
break;
caseR.id.button3://绑定服务
System.out.println("服务click button3");
//Context.BIND_AUTO_CREATE:当定的服务不存在时候则自动创建对应服务
//conn ServiceConnection的实例化对象,帮助家随时了解疫情动向。点击播放 GIF 0.0M接下来咱们说说具体的操作步骤:步骤1依次单击【数据】【自网站】,用于服务连接成功与连接中断的处理接口
bindService(intent,conn,Context.BIND_AUTO_CREATE);
break;
caseR.id.button4://解除绑定服务
unbindService(conn);
break;
}
}
private classMyConnimplementsServiceConnection{
//绑定一个服务成功的时候 调用onServiceConnected
@Override
public voidonServiceConnected(ComponentNamename,IBinderservice) {}
@Override
public voidonServiceDisconnected(ComponentNamename) {}
}
}
MyService.java:
packagecom.exle.servicelifecycle;
importandroid.app.Service;
importandroid.content.Intent;
importandroid.os.IBinder;
public classMyServiceextendsService{
@Override
publicIBinderonBind(Intentintent) {
System.out.println("服务on bind");
return null;
}
@Override
public booleanonUnbind(Intentintent) {
System.out.println("服务on unbind");
return super.onUnbind(intent);
}
@Override
public voidonCreate() {
System.out.println("服务oncreate");
super.onCreate();
}
@Override
public voidonStart(Intentintent,intstartId) {
System.out.println("服务onstart");
super.onStart(intent, startId);
}
//
@Override
public voidonDestroy() {
System.out.println("服务ondestroy");
super.onDestroy();
}
}
AndroidManifest.xml:
xml version="1.0"encoding="utf-8"?>
package="com.exle.servicelifecycle">
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Servicelifecycle">
然后将项目署到设备中
当第一次顺序操作了服务绑定、解除绑定经历了oncreate、onbind、unbind、ondestroy
不断的这样的操作步骤,在弹出的对话框中输入以下网址:http://m.medsci.cn/wh.asp步骤2在导航器对话框中单击“Table0”,可以发现每次绑定都要create,然后单击【转换数据】:步骤3“疑似”这一列的数据看起来不太完整,这说明每次解绑时候和onstop有点类似,咱们先不要了。单击这一列的列标,直接把服务给删除了,删除。步骤4先添加序号。然后对序号筛选一下,因为我们这里绑定的时候是添加了Context.BIND_AUTO_CREATE绑定模式的,这里咱们先保留前10项的数据,即当服务不存在的时候就自动创建。
再来看看在已绑定服务的情况下继续绑定服务的操作
当已绑定服务的时候再次绑定服务的时候就不会产生任何生命周期的日志了,项目多了,这里是已经绑定的情况下,一会儿生成的图表会比较凌乱。右键单击序号列,筛选“服务”关键字的日志,删除。步骤5右键单击“地区”列,随着你不断的点击绑定服务,会发现永远也不会再次运行生命周期的相关方法了
服务绑定与服务开启的区别
服务绑定则服务会随着activity的关闭而自动销毁,例如这里我退出程序了(在这个项目中相当于把activity关闭了),服务就自动解绑了
不过即便不用服务绑定的方式,用普通的服务启动的方式,也可以在activity的onDestroy(在activity被销毁时执行)方法的覆写中编写让对应服务停止的操作。
例如MainActivity.java:
packagecom.exle.servicelifecycle;
importandroidx.appcompat.app.AppCompatActivity;
importandroid.content.ComponentName;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.content.ServiceConnection;
importandroid.os.Bundle;
importandroid.os.IBinder;
importandroid.view.View;
importandroid.widget.Button;
public classMainActivityextendsAppCompatActivityimplementsView.OnClickListener{
Buttonbt_start;
Buttonbt_stop;
Buttonbt_bind_service;//绑定服务
Buttonbt_unbind_service;//解除绑定服务
Intentintent;
MyConnconn;
@Override
protected voidonCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_start= (Button)this.findViewById(R.id.button);
bt_stop= (Button)this.findViewById(R.id.button2);
bt_bind_service= (Button)this.findViewById(R.id.button3);
bt_unbind_service= (Button)this.findViewById(R.id.button4);
bt_start.setOnClickListener(this);
bt_stop.setOnClickListener(this);
bt_bind_service.setOnClickListener(this);
bt_unbind_service.setOnClickListener(this);
//自定义MyService实现服务意图
intent=newIntent(this,MyService.class);
conn=newMyConn();
}
@Override
public voidonClick(Viewv) {
switch(v.getId()) {
caseR.id.button://开启服务
startService(intent);
break;
caseR.id.button2://停止服务
stopService(intent);
System.out.println("服务click button2");
break;
caseR.id.button3://绑定服务
System.out.println("服务click button3");
//Context.BIND_AUTO_CREATE:当定的服务不存在时候则自动创建对应服务
//conn ServiceConnection的实例化对象,用于服务连接成功与连接中断的处理接口
bindService(intent,conn,Context.BIND_AUTO_CREATE);
break;
caseR.id.button4://解除绑定服务
unbindService(conn);
break;
}
}
private classMyConnimplementsServiceConnection{
//绑定一个服务成功的时候 调用onServiceConnected
@Override
public voidonServiceConnected(ComponentNamename,IBinderservice) {}
@Override
public voidonServiceDisconnected(ComponentNamename) {}
}
@Override
protected void onDestroy() {
stopService(intent);
super.onDestroy();
}
}
然后署到设备上操作开启服务、然后退出到桌面
另外据说即便是在以绑定服务的方式时候也要覆写activity的onDestroy方法中编写使对应服务解除绑定的操作,不然在activity关闭后会报错包含“android.app.ServiceConnectionLeaked”信息的一个错误信息。
例如可以覆写如:
MainActivity.java:
packagecom.exle.servicelifecycle;
importandroidx.appcompat.app.AppCompatActivity;
importandroid.content.ComponentName;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.content.ServiceConnection;
importandroid.os.Bundle;
importandroid.os.IBinder;
importandroid.view.View;
importandroid.widget.Button;
public classMainActivityextendsAppCompatActivityimplementsView.OnClickListener{
Buttonbt_start;
Buttonbt_stop;
Buttonbt_bind_service;//绑定服务
Buttonbt_unbind_service;//解除绑定服务
Intentintent;
MyConnconn;
@Override
protected voidonCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_start= (Button)this.findViewById(R.id.button);
bt_stop= (Button)this.findViewById(R.id.button2);
bt_bind_service= (Button)this.findViewById(R.id.button3);
bt_unbind_service= (Button)this.findViewById(R.id.button4);
bt_start.setOnClickListener(this);
bt_stop.setOnClickListener(this);
bt_bind_service.setOnClickListener(this);
bt_unbind_service.setOnClickListener(this);
//自定义MyService实现服务意图
intent=newIntent(this,MyService.class);
conn=newMyConn();
}
@Override
public voidonClick(Viewv) {
switch(v.getId()) {
caseR.id.button://开启服务
startService(intent);
break;
caseR.id.button2://停止服务
stopService(intent);
System.out.println("服务click button2");
break;
caseR.id.button3://绑定服务
System.out.println("服务click button3");
//Context.BIND_AUTO_CREATE:当定的服务不存在时候则自动创建对应服务
//conn ServiceConnection的实例化对象,用于服务连接成功与连接中断的处理接口
bindService(intent,conn,Context.BIND_AUTO_CREATE);
break;
caseR.id.button4://解除绑定服务
unbindService(conn);
break;
}
}
private classMyConnimplementsServiceConnection{
//绑定一个服务成功的时候 调用onServiceConnected
@Override
public voidonServiceConnected(ComponentNamename,IBinderservice) {}
@Override
public voidonServiceDisconnected(ComponentNamename) {}
}
@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}
}
不过经过我的测试,这家伙可有可无,我发现无论有没有最后都执行了服务的onDestory方法,且没有出现上面类似错误。可能与sdk版本有关的,我用的安卓9的sdk,应该是相比较高的版本,没有这个问题吧。
另外还有最后一个明显的区别就是以startService形式实现的服务则无法调用服务类里面的方法。而以绑定形式实现的服务则可以调用服务类里面的方法。
调用服务类里面的方法
上面已经了解了,以绑定服务的方式,则可以调用服务类里面的方法,那么具体实现则
观察onBind方法返回值类型是Ibinder,也就是返回Ibinder的实例
那么这个Ibinder的实例中提供一个方法可以被外能够访问即可。
然而这个Ibinder类需要我们继承Binder类,并实现一个接口,该接口中提供上面我们说的这个可以被外访问的方法。
那么假如这个要实现的接口我们建立为Iservice.java:
所以在MyService.java中onbind可以这样实现:
packagecom.exle.servicelifecycle;
importandroid.app.Service;
importandroid.content.Intent;
importandroid.os.Binder;
importandroid.os.IBinder;
public classMyServiceextendsService{
/**
*服务里面的一个方法
*/
public void sayHelloInService(){
System.out.println("hello in service");
}
public class MyBinder extends Binder implements IService{
@Override
public void callMethodInService() {
System.out.println("服务 调用了callMethodInService");
sayHelloInService();
}
}
@Override
publicIBinderonBind(Intentintent) {
System.out.println("服务on bind");
return new MyBinder();
}
@Override
public booleanonUnbind(Intentintent) {
System.out.println("服务on unbind");
return super.onUnbind(intent);
}
@Override
public voidonCreate() {
System.out.println("服务oncreate");
super.onCreate();
}
@Override
public voidonStart(Intentintent,intstartId) {
System.out.println("服务onstart");
super.onStart(intent, startId);
}
//
@Override
public voidonDestroy() {
System.out.println("服务ondestroy");
super.onDestroy();
}
}
那么接下来再来一个按钮来调用服务里面的方法activity_main.xml:
xml version="1.0"encoding="utf-8"?>
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开启服务"/>
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="关闭服务"/>
android:id="@+id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="绑定服务"/>
android:id="@+id/button4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="解除绑定服务"/>
android:id="@+id/button5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="调用服务里面的方法" />
然后是调用服务里面的方法的具体事件实现MainActivity.java:
packagecom.exle.servicelifecycle;
importandroidx.appcompat.app.AppCompatActivity;
importandroid.content.ComponentName;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.content.ServiceConnection;
importandroid.os.Bundle;
importandroid.os.IBinder;
importandroid.view.View;
importandroid.widget.Button;
public classMainActivityextendsAppCompatActivityimplementsView.OnClickListener{
Buttonbt_start;
Buttonbt_stop;
Buttonbt_bind_service;//绑定服务
Buttonbt_unbind_service;//解除绑定服务
Intentintent;
MyConnconn;
Buttonbt_call_service;
IServiceiService;
@Override
protected voidonCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_start= (Button)this.findViewById(R.id.button);
bt_stop= (Button)this.findViewById(R.id.button2);
bt_bind_service= (Button)this.findViewById(R.id.button3);
bt_unbind_service= (Button)this.findViewById(R.id.button4);
bt_call_service= (Button)this.findViewById(R.id.button5);
bt_call_service.setOnClickListener(this);
bt_start.setOnClickListener(this);
bt_stop.setOnClickListener(this);
bt_bind_service.setOnClickListener(this);
bt_unbind_service.setOnClickListener(this);
//自定义MyService实现服务意图
intent=newIntent(this,MyService.class);
conn=newMyConn();
}
@Override
public voidonClick(Viewv) {
switch(v.getId()) {
caseR.id.button://开启服务
startService(intent);
break;
caseR.id.button2://停止服务
stopService(intent);
System.out.println("服务click button2");
break;
caseR.id.button3://绑定服务
System.out.println("服务click button3");
//Context.BIND_AUTO_CREATE:当定的服务不存在时候则自动创建对应服务
//conn ServiceConnection的实例化对象,用于服务连接成功与连接中断的处理接口
bindService(intent,conn,Context.BIND_AUTO_CREATE);
break;
caseR.id.button4://解除绑定服务
unbindService(conn);
break;
case R.id.button5://调用服务里面的方法
iService.callMethodInService();
break;
}
}
private classMyConnimplementsServiceConnection{
//绑定一个服务成功的时候 调用onServiceConnected
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iService = (IService) service;
}
@Override
public voidonServiceDisconnected(ComponentNamename) {}
}
}
最后署到设备中测试是ok的
标签: