可以使bindService()成为阻塞吗?

vip*_*ipw 11 android

我有一个使用远程服务的Android应用程序,我绑定它bindService(),这是异步的.

在绑定服务之前,应用程序是无用的,所以我想在任何Activity启动之前等待绑定完成.有没有办法让服务绑定之前onCreate()或被onResume()调用?我认为可能有办法进行绑定Application.有任何想法吗?

编辑:

如果在onCreate()我这样做.

bindService(service, mWebServiceConnection, BIND_AUTO_CREATE);
synchronized (mLock) { mLock.wait(40000); }
Run Code Online (Sandbox Code Playgroud)

ServiceConnection.onServiceConnected不会被调用40秒.很明显,如果我想要服务绑定,我必须让onCreate()返回.

所以似乎没有办法做我想要的.

编辑2: Android我如何等待服务实际连接?对绑定服务时Android中发生的事情有一些很好的评论.

mah*_*mah 6

你不能拥有bindService()块.但是,您的ServiceConnection(bindService的第二个参数)具有回调功能,可以告诉您服务何时连接和断开连接,因此您可以使用其他代码块,直到您的onServiceConnected()方法解除阻塞.

  • 你可以在onStart中调用bindService,然后显示无限的ProgressDialog,直到触发ServiceConnection的onServiceConnected方法.如果bindService调用失败,请使用Handler超时. (6认同)
  • @Femi不,你不能阻止`bindService()`.原因是你总是在主线程上回调.如果你在调用后阻塞(例如,`wait()`),你将永远不会被回调...因为你永远不会将控制权交还给looper. (3认同)

Ale*_*sio 6

当我需要在做其他事情之前等待服务被绑定时我会玩锁.确切地说,ServiceConnection拥有一个锁定对象并暴露一个waitUntilConnected阻塞锁定的方法,直到唤醒信号.该通知位于onServiceConnected回调中.

public class MyServiceConnection implements ServiceConnection {

    private volatile boolean connected = false;
    private Object lock = new Object();

    @Override
    public void onServiceConnected(ComponentName name, IBinder binder) {
        connected = true;

        synchronized (lock) {
            lock.notifyAll();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        connected = false;
    }

    public void waitUntilConnected() throws InterruptedException {
        if (!connected) {
            synchronized (lock) {
                lock.wait();
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

因此,例如,如果活动必须等待服务绑定,它只调用该waitUntilConnected方法.

protected void onStart() {
    super.onStart();

    bindService(myServiceIntent, myServiceConnection, Context.BIND_AUTO_CREATE);
    try {
        myServiceConnection.waitUntilConnected();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

我把waitUntilConnected方法放在onStart一个例子中,但必须在另一个线程中调用它.我想听一个更优雅的方式!:)

  • 如何在没有死锁的情况下工作?一切都发生在同一个线程中. (6认同)
  • 这可以工作吗?ServiceConnection的文档说,就像系统中的许多回调一样,此类的方法是从进程的主线程调用的。 (2认同)

Ran*_*ku' 5

似乎有一种方法可以做到这一点。KeyChain.java并且几个 Google 编写的类使用 aLinkedBlockingQueue来允许同步绑定到服务。

例如,请参阅bind在此调用的方法:https : //github.com/android/platform_frameworks_base/blob/master/keystore/java/android/security/KeyChain.java

由于使用了阻塞队列,它似乎是同步返回服务对象。

不幸的是,如 Android 文档https://developer.android.com/reference/android/security/KeyChain.html 所述InterruptedException由于从队列中获取元素,可能会在等待时中断,因此某些方法会抛出。

  • 使用 BlockingQueue 是一种聪明的方法,可以在服务连接之前阻塞运行 KeyChain.bind() 的线程。**但是** 当从主/UI 线程调用时,这将不起作用,因为对 ServiceConnection.onServiceConnected() 的调用会排队(例如,使用任务执行器)而不是并行运行。对 onServiceConnected() 的调用将永远不会运行,直到线程的当前任务完成...但它会被 BlockingQueue.take() 阻塞。我假设 KeyChain 的上下文实现 bindService() 并行调用 onServiceConnected(),这与 Activity 的实现不同。 (5认同)