我最终得到了这样的结果:
1)为了给辅助的东西一些范围,我创建了一个内部类。至少,丑陋的内部与其余代码是分开的。我需要一个远程服务做某事Something
,因此类名中的单词
private RemoteSomethingHelper mRemoteSomethingHelper = new RemoteSomethingHelper();
class RemoteSomethingHelper {
//...
}
2) 调用远程服务方法需要两件事:IBinder 和要执行的代码。因为我们不知道哪个先被知道,所以我们存储它们:
private ISomethingService mISomethingService;
private Runnable mActionRunnable;
每次我们写入这些文件之一时,我们都会调用_startActionIfPossible()
:
private void _startActionIfPossible() {
if (mActionRunnable != null && mISomethingService != null) {
mActionRunnable.run();
mActionRunnable = null;
}
}
private void performAction(Runnable r) {
mActionRunnable = r;
_startActionIfPossible();
}
当然,这假设 Runnable 可以访问 mISomethingService,但对于在RemoteSomethingHelper
类的方法中创建的 runnables 也是如此。
在 UI 线程上ServiceConnection
调用回调真的很好:如果我们要从主线程调用服务方法,我们不需要关心同步。
ISomethingService
当然,是通过 AIDL 定义的。
3) 我们不只是将参数传递给方法,而是创建一个 Runnable,稍后当可以调用时,它将使用这些参数调用该方法:
private boolean mServiceBound;
void startSomething(final String arg1) {
// ... starting the service ...
final String arg2 = ...;
performAction(new Runnable() {
@Override
public void run() {
try {
// arg1 and arg2 must be final!
mISomethingService.startSomething(arg1, arg2);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
4)最后,我们得到:
private RemoteSomethingHelper mRemoteSomethingHelper = new RemoteSomethingHelper();
class RemoteSomethingHelper {
private ISomethingService mISomethingService;
private Runnable mActionRunnable;
private boolean mServiceBound;
private void _startActionIfPossible() {
if (mActionRunnable != null && mISomethingService != null) {
mActionRunnable.run();
mActionRunnable = null;
}
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
// the methods on this class are called from the main thread of your process.
@Override
public void onServiceDisconnected(ComponentName name) {
mISomethingService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mISomethingService = ISomethingService.Stub.asInterface(service);
_startActionIfPossible();
}
}
private void performAction(Runnable r) {
mActionRunnable = r;
_startActionIfPossible();
}
public void startSomething(final String arg1) {
Intent intent = new Intent(context.getApplicationContext(),SomethingService.class);
if (!mServiceBound) {
mServiceBound = context.getApplicationContext().bindService(intent, mServiceConnection, 0);
}
ComponentName cn = context.getApplicationContext().startService(intent);
final String arg2 = ...;
performAction(new Runnable() {
@Override
public void run() {
try {
mISomethingService.startSomething(arg1, arg2);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
}
context
是我班上的一个领域;在一个活动中,您可以将其定义为Context context=this;
我不需要排队操作;如果你这样做,你可以实现它。
您可能需要在 startSomething(); 中进行结果回调;我做到了,但这没有在这段代码中显示。