我将我的 Android 应用程序的一部分实现为两个本地绑定服务,一个依赖于另一个。(我只bindService()
与它们一起使用;从不startService()
。)但是,当我绑定具有依赖项的服务时,我会在它自己的依赖项准备好之前获得对它的“绑定”和“连接”引用。这使得对其某些方法的调用失败。如何确保在连接其依赖服务之前不使用我的服务?我可以延迟我的服务的连接直到它自己的依赖项被连接吗?
通常,人们只会获得对已准备好使用的绑定服务的引用,因为onCreate()
它们onBind()
已经被调用过。但是,当您为服务调用bindService()
服务onCreate()
时A
,连接到B
的onServiceConnected()
回调B
可以(在我的情况下是!)在连接到之后调用。默认情况下,一切都在同一个(主 UI)线程中运行,因此您不能只在连接返回之前让'等待连接。onServiceConnected()
A
A
onBind()
B
我做了一个简单的应用程序来演示这个问题。以下是相关摘录。我的活动加载具有依赖项的服务,ServiceA
:
public class MainActivity extends Activity {
private ServiceA serviceA;
private final ServiceConnection connectionA = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
serviceA = ((ServiceA.Binder) service).getService();
setGreeting();
}
@Override
public void onServiceDisconnected(ComponentName name) {
serviceA = null;
}
};
protected void setGreeting() {
String greeting = serviceA.getGreeting();
TextView textView = (TextView) findViewById(R.id.greeting);
textView.setText(greeting);
}
@Override
protected void onStart() {
super.onStart();
bindService(new Intent(this, ServiceA.class),
connectionA, Context.BIND_AUTO_CREATE);
}
/* ... */
}
这是ServiceB
,这ServiceA
取决于:
public class ServiceB extends Service {
public class Binder extends android.os.Binder {
public ServiceB getService() {
return ServiceB.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return new Binder();
}
public String getGreeting() {
return "Hello";
}
}
这是ServiceA
:
public class ServiceA extends Service {
public class Binder extends android.os.Binder {
public ServiceA getService() {
return ServiceA.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return new Binder();
}
private ServiceB serviceB;
private final ServiceConnection connectionB = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
serviceB = ((Service1.Binder) service).getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
serviceB = null;
}
};
@Override
public void onCreate() {
bindService(new Intent(this, ServiceB.class),
connectionB, Context.BIND_AUTO_CREATE);
super.onCreate();
}
@Override
public void onDestroy() {
unbindService(connectionB);
super.onDestroy();
}
public String getGreeting() {
return serviceB.getGreeting() + "!";
}
}
我已将这两项服务添加到AndroidManifest.xml
. 当我运行它时,serviceB
正在null
调用serviceA.getGreeting()
from setGreeting()
,因为connectionB.onServiceConnected()
还没有被调用。
有什么方法可以让我connectionA.onServiceConnected()
只有在被调用后才能被调用connectionB.onServiceConnected()
?或者我怎么能确保我不使用serviceB
之前serviceA.serviceB
已经设置?
我注意到,如果不是setGreeting()
直接调用 in onServiceConnected()
,而是直接调用post()
到 looper 队列的末尾,问题似乎就消失了:
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
serviceA = ((ServiceA.Binder) service).getService();
new Handler(getMainLooper()).post(new Runnable() {
@Override
public void run() {
setGreeting();
}
});
}
我想这是因为所有onServiceConnected()
要进行的调用都恰好在 looper 的队列中,所以通过等待所有当前任务,在被调用serviceA.serviceB
时已经准备好。setGreeting()
但这对我来说并不可靠。这可靠吗?有没有更可靠的方法可以等到我的服务准备好?