回调是否发生在主(UI)线程上?

有很多Android SDK API注册了回调处理程序。 举一个具体的例子,使用MediaPlayer可以设置onCompletionListener回调。 这些回调是否会从主(UI)线程调用? 如果答案是“它取决于”,那么我正在寻找一些关于从主线程调用哪个回调而不是另一个线程的一般规则。 SDK文档似乎没有说出来。 (也许我错过了。)

知道这一点似乎很重要,因为如果我保证主线程回调,那么我可以跳过代码中不同位置之间共享的数据的一些线程同步。 如果我因无知而被迫悲观,那么我必须编写额外的同步块代码并担心死锁,数据完整性和性能降低。

Related of "回调是否发生在主(UI)线程上?"

Android将在其他线程上调用您的代码的一种情况是,如果您创建通过AIDL公开的远程服务 – 将在绑定器线程上调用这些AIDL方法,而不是主应用程序线程。

但是,这是个例外。 正如其他人所指出的那样,绝大多数这些都是在主应用程序线程上调用的。

如有疑问,可以使用Log.i("TAG", Thread.currentThread().getName()); 并看到:)

根据我的经验,这些回调总是回到非UI线程上。 您是否尝试过Activity.runOnUiThread()以确保您的代码在UI线程上运行? 您仍然会受到性能影响,因为此代码运行需要更长时间,但您可以避免线程同步的一些常见问题。

通常,回调将发生在运行事件的线程上。 如果您注册了一个回调并开始在非UI线程上播放,那么回调将在非UI线程上发生。 但是,Android不会自己在后台创建新线程。

所有与UI相关的事件必须在UI线程上发生,因此您可以预测在UI线程上将发生单击处理程序回调等。

正如Aaron C指出的那样,你可以使用Activity.runOnUiThread强制在那里发生事情。

此外, AsyncTask对于快速后台工作非常有用,您需要一些完成步骤才能在uI线程上进行操作。

编辑:评论中的示例。

 public void MyWorker { private OnCompleteListener onCompleteListener; public void setOnCompleteListener(OnCompleteListener onCompleteListener) { this.onCompleteListener = onCompleteListener; } public void doWork() { // do lots of work here onCompleteListener.onComplete(); } } // somewhere in my Activity public void onCreate() { final MyWorker worker = new MyWorker(); worker.setOnCompleteListener(new OnCompleteListener() { ... }); new Thread(new Runnable() { public void run() { worker.doWork(); } }).start(); } 

在此示例中,将从非UI线程运行onComplete“回调”。 线程将在onComplete完成后退出。

另一个例外是当您使用WebView时。 当javascript调用Java函数时,这种调用不会发生在主线程中

当我在使用Location API时,出现了类似的东西。 我们知道,我们为位置服务提供回调,以便在获得位置后收到通知。 所以我在这个回调中做了一些事情,这花了很长时间,比如使用Geocoder API。

我之前的印象是,这个回调将从其他线程调用,因此不会在主UI线程上执行。 但我可以看到,事实并非如此。

那么我在这个监听器中编写的代码将在主线程上执行。

现在我不明白的是他们如何设法做到这一点,是通过使用标准函数runOnUIThread() ???