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

时间:2011-06-24 18:43:58

标签: android

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

在服务绑定之前,应用程序是无用的,所以我想等到绑定完成后再启动任何Activity。有没有办法在调用onCreate()onResume()之前绑定服务?我认为可能有办法在Application中进行绑定。有什么想法吗?

编辑:

如果在onCreate()我这样做。

bindService(service, mWebServiceConnection, BIND_AUTO_CREATE);
synchronized (mLock) { mLock.wait(40000); }

ServiceConnection.onServiceConnected在40秒内未被调用。很明显,如果我希望服务绑定,我必须让onCreate()返回。

所以似乎没有办法做我想做的事。

编辑2: Android how do I wait until a service is actually connected?对绑定服务时Android中发生的事情有一些很好的评论。

5 个答案:

答案 0 :(得分:7)

当我需要在做其他事情之前等待服务被绑定时,我会玩锁。确切地说,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();
            }
        }
    }

}

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

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

    bindService(myServiceIntent, myServiceConnection, Context.BIND_AUTO_CREATE);
    try {
        myServiceConnection.waitUntilConnected();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

我将waitUntilConnected方法放在onStart中仅作为示例,但必须在不同的线程中调用。我想听一个更优雅的方式! :)

答案 1 :(得分:6)

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

答案 2 :(得分:4)

似乎有办法做到这一点。 KeyChain.java和几个Google编写的类使用LinkedBlockingQueue来同步绑定到服务。

例如,请参阅此https://github.com/android/platform_frameworks_base/blob/master/keystore/java/android/security/KeyChain.java

上名为bind的方法

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

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

答案 3 :(得分:0)

bindService()无法阻止。这种做法挫败了Service的整个目的。您说整个UI包含来自服务的结果。我认为您需要重新考虑您的UI并使用某种中间表示填充它,向用户显示应用正在收集数据。

答案 4 :(得分:0)

Android 10 在绑定到服务以提供 Executor(可以从 Executor 创建)时引入了新的 bindService 方法签名。

/**
     * Same as {@link #bindService(Intent, ServiceConnection, int)} with executor to control
     * ServiceConnection callbacks.
     * @param executor Callbacks on ServiceConnection will be called on executor. Must use same
     *      instance for the same instance of ServiceConnection.
    */
    public boolean bindService(@RequiresPermission @NonNull Intent service,
            @BindServiceFlags int flags, @NonNull @CallbackExecutor Executor executor,
            @NonNull ServiceConnection conn) {
        throw new RuntimeException("Not implemented. Must override in a subclass.");
    }

看到这个Answer