我正在使用来自Guava的ListenableFuture,关于它们的一件好事是,将Executor传递给该Futures.addCallback
方法,即要求在给定的线程/执行器上执行回调。
在我的Android应用程序中,我希望能够基于ListenableFuture
UI线程启动异步执行,并计划一个也在UI线程上执行的回调。因此,我想以某种方式将UI线程执行器提交到上述Futures.addCallback
方法。如何实现?
或者,换句话说,我想要UI线程的执行程序。它已经在Android中可用,或者,如果我必须创建自己的,我该怎么做?
编辑:作为此问题的扩展,是否可以做同样的事情,但不仅可以使用UI线程,还可以使用对调用异步方法进行调用的任何特定线程?
我很高兴知道如何在不使用Android特有的东西(例如Handler
和)的情况下实现相同的效果,而Looper
仅使用纯Java。
我想我已经看到一些实现方式。基本思路大致是
class UiThreadExecutor implements Executor {
private final Handler mHandler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
您可以通过将任何内容传递给主线程的处理程序来委派运行任何内容。
Edit2:您可以配置处理程序,例如SensorManager#registerListener(..., Handler handler)
允许您这样做。
class HandlerThreadExecutor implements Executor {
private final Handler mHandler;
public HandlerThreadExecutor(Handler optionalHandler) {
mHandler = optionalHandler != null ? optionalHandler : new Handler(Looper.getMainLooper());
}
@Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
与使用当前线程的循环程序相比,其优势在于,它可以使您明确Looper
使用哪个线程。在您的解决方案中,您可以使用Looper调用任何线程new ExecuteOnCaller()
,而这通常不是您稍后在其中运行代码的线程。
我很高兴知道如何仅使用纯Java就无需使用诸如Handler和Looper之类的Android特有的东西就能达到相同的效果。
Looper
,Handler
和后面所有的逻辑消息队列由大多纯Java的。通用解决方案的问题在于,您无法“注入”代码以运行到线程中。线程必须定期检查某种任务队列,以查看是否有要运行的东西。
如果您编写类似的代码
new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.interrupted()) {
System.out.println("Hello");
}
}
}).start();
然后,除了不断打印“ Hello”之外,没有其他方法可以使该线程执行任何其他操作。如果可以的话,这就像在程序代码中动态插入到其他代码的跳转一样。IMO将是一个可怕的想法。
final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
Runnable codeToRunInThisThread = queue.take();
codeToRunInThisThread.run();
}
} catch (InterruptedException ignored) {}
}
}).start();
另一方面,一个简单的线程会在队列中永远循环。该线程可以在两者之间执行其他任务,但是您必须在代码中添加手动检查。
您可以通过发送任务
queue.put(new Runnable() {
@Override
public void run() {
System.out.println("Hello!");
}
});
这里没有定义特殊的处理程序,但这是Handler&Looper在Android中所做的工作的核心。Handler
在Android中,您可以为Message
而不是定义回调Runnable
。
Executors.newCachedThreadPool()
和类似的东西大致相同。在一个队列中只有多个线程在等待代码。
作为对该问题的扩展,是否可以做同样的事情,而不仅是使用UI线程,而是使用任何特定线程来调用异步方法?
通用答案是“否”。仅当有一种方法可以注入代码在该线程中运行时。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句