我有一个绑定到持久服务的Android应用程序(一旦以startService()
开头)。
该服务是应用程序不可或缺的一部分,因此几乎在每个Activity中都使用。因此,我想只绑定一次服务(而不是在每个Activity中绑定/解除绑定)并在我的应用程序的生命周期内保持绑定。
我已从Application扩展并绑定到Application#onCreate()中的服务。但是我现在遇到的问题是我不知道我的应用程序何时存在,因为从未调用Application#onTerminate(),请参阅JavaDoc:
此方法适用于模拟过程环境。永远不会 在生产Android设备上调用,删除进程 简单地杀死他们;没有用户代码(包括此回调) 执行时执行。
那么如何从Application中绑定的服务中干净地取消绑定?
答案 0 :(得分:13)
我通过计算Application
中对服务绑定的引用来解决这个问题。每个Activity
必须在acquireBinding()
方法中调用onCreate()
,并在releaseBinding()
中致电onDestroy()
。如果引用计数器达到零,则释放绑定。
以下是一个例子:
class MyApp extends Application {
private final AtomicInteger refCount = new AtomicInteger();
private Binding binding;
@Override
public void onCreate() {
// create service binding here
}
public Binding acquireBinding() {
refCount.incrementAndGet();
return binding;
}
public void releaseBinding() {
if (refCount.get() == 0 || refCount.decrementAndGet() == 0) {
// release binding
}
}
}
// Base Activity for all other Activities
abstract class MyBaseActivity extend Activity {
protected MyApp app;
protected Binding binding;
@Override
public void onCreate(Bundle savedBundleState) {
super.onCreate(savedBundleState);
this.app = (MyApp) getApplication();
this.binding = this.app.acquireBinding();
}
@Override
public void onDestroy() {
super.onDestroy();
this.app.releaseBinding();
}
}
答案 1 :(得分:4)
来自Sven的回答:
我通过计算对服务的引用来解决这个问题 应用程序中的绑定。每个活动都必须打电话 在他们的onCreate()方法中的acquireBinding()并调用releaseBinding() 在onDestroy()中。如果引用计数器达到零,则绑定为 释放。
我同意,但你不应该在onDestroy中这样做 - 通常不会被调用。
相反,我建议以下内容(基于您的代码示例)...
// Base Activity for all other Activities
abstract class MyBaseActivity extend Activity {
protected MyApp app;
protected Binding binding;
@Override
public void onCreate(Bundle savedBundleState) {
super.onCreate(savedBundleState);
this.app = (MyApp) getApplication();
this.binding = this.app.acquireBinding();
}
@Override
protected void onPause() {
super.onPause();
// Pre-HC, activity is killable after this.
if ((11 > Build.VERSION.SDK_INT) && (isFinishing()))
onFinishing();
}
@Override
protected void onStop() {
super.onStop();
if ((10 < Build.VERSION.SDK_INT) && (isFinishing()))
onFinishing();
}
protected void onFinishing() {
// Do all activity clean-up here.
this.app.releaseBinding();
}
}
但是,我对isFinishing()的使用只是一个想法 - 我不确定它是否可靠。也许onPause / onStop使用isFinishing()调用false,但随后活动被杀死 - 而且你的releaseBinding()永远不会被调用。
如果你摆脱isFinishing检查,我认为你需要将acquireBinding()调用从onCreate移动到onStart / onResume(取决于sdk版本),以确保你的引用计数不会搞砸。
谁知道发布应用程序的服务会非常复杂!
答案 2 :(得分:2)
在这种情况下是否需要解除绑定?应用程序无论如何都会被杀死。我尝试在不解除绑定的情况下实现一个示例应用程序,它似乎正常工作。