在Android的IntentService中等待异步回调

caw*_*caw 28 java android asynchronous intentservice

我有一个IntentService在另一个类中启动异步任务,然后应该等待结果.

问题是方法运行完毕后IntentService会立即onHandleIntent(...)完成,对吧?

这意味着,通常,IntentService在启动异步任务后会立即关闭,并且不再存在以接收结果.

public class MyIntentService extends IntentService implements MyCallback {

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected final void onHandleIntent(Intent intent) {
        MyOtherClass.runAsynchronousTask(this);
    }

}

public interface MyCallback {

    public void onReceiveResults(Object object);

}

public class MyOtherClass {

    public void runAsynchronousTask(MyCallback callback) {
        new Thread() {
            public void run() {
                // do some long-running work
                callback.onReceiveResults(...);
            }
        }.start();
    }

}
Run Code Online (Sandbox Code Playgroud)

如何使上面的代码段工作?我已经尝试在启动任务后放入Thread.sleep(15000)(任意持续时间)onHandleIntent(...).它似乎工作.

但它绝对不是一个干净的解决方案.也许甚至有一些严重的问题.

更好的解决方案?

cor*_*992 18

使用标准Service类而不是IntentService,从onStartCommand()回调中启动异步任务,并Service在收到完成回调时销毁它.

问题是如果在已经运行时再次启动Service任务而同时运行任务的情况下正确处理销毁Service.如果您需要处理这种情况,那么您可能需要设置一个运行计数器或一组回调,并Service在它们全部完成时销毁它们.

  • 同意.`IntentService`不是为这种情况设计的. (9认同)
  • @AdamJohns:"然而,等待来自IntentService内部的http调用的回调并不是IntentService的设计目的" - 在这种情况下我不知道你的"回调"是什么意思.对于"IntentService"来说,执行HTTP I/O是一件非常合理的事情,只要它同步执行即可.如果您对此领域有其他疑虑,我建议您提出单独的Stack Overflow问题. (2认同)

Mat*_*ola 12

我同意corsair992,通常你不必从IntentService进行异步调用,因为IntentService已经在工作线程上完成了它的工作.但是,如果必须这样做,则可以使用CountDownLatch.

public class MyIntentService extends IntentService implements MyCallback {
    private CountDownLatch doneSignal = new CountDownLatch(1);

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected final void onHandleIntent(Intent intent) {
        MyOtherClass.runAsynchronousTask(this);
        doneSignal.await();
    }

}

@Override
public void onReceiveResults(Object object) {
    doneSignal.countDown();
}

public interface MyCallback {

    public void onReceiveResults(Object object);

}

public class MyOtherClass {

    public void runAsynchronousTask(MyCallback callback) {
        new Thread() {
            public void run() {
                // do some long-running work
                callback.onReceiveResults(...);
            }
        }.start();
    }

}
Run Code Online (Sandbox Code Playgroud)


小智 6

如果您仍在寻找使用Intent Service进行异步回调的方法,您可以在线程上等待并通知如下,

private Object object = new Object();

@Override
protected void onHandleIntent(Intent intent) {
    // Make API which return async calback.

    // Acquire wait so that the intent service thread will wait for some one to release lock.
    synchronized (object) {
        try {
            object.wait(30000); // If you want a timed wait or else you can just use object.wait()
        } catch (InterruptedException e) {
            Log.e("Message", "Interrupted Exception while getting lock" + e.getMessage());
        }
    }
}

// Let say this is the callback being invoked
private class Callback {
    public void complete() {
        // Do whatever operation you want

        // Releases the lock so that intent service thread is unblocked.
        synchronized (object) {
            object.notifyAll();
        }   
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你能不能这样做 (2认同)