Выполняются ли обратные вызовы в основном потоке (UI)?

Существует множество Android SDK API, в которых зарегистрированы обработчики обратного вызова. Для конкретного примера, с помощью MediaPlayer вы можете установить обратный вызов onCompletionListener. Будут вызваны эти обратные вызовы из основного (UI) потока? Если ответ «это зависит», то я ищу некоторые общие правила для того, какие вызовы будут вызываться из основного потока по сравнению с другим потоком. Документация SDK, похоже, не говорит об этом. (Возможно, я пропустил это.)

Кажется, важно знать, потому что, если мне гарантированы обратные вызовы основного потока, то я могу пропустить некоторую синхронизацию потоков данных, разделяемых между разными местами кода. Если я вынужден быть пессимистичным из-за невежества, тогда я должен написать дополнительный код блока синхронизации и беспокоиться о взаимоблокировках, целостности данных и сниженной производительности.

Solutions Collecting From Web of "Выполняются ли обратные вызовы в основном потоке (UI)?"

Один случай, когда Android будет вызывать ваш код в каком-то другом потоке, будет, если вы создадите удаленную службу, открытую через AIDL – эти методы AIDL будут вызываться в потоке связующего, а не в главном потоке приложения.

Однако это исключение. Как отмечали другие, подавляющее большинство из них называется основной темой приложения.

В случае сомнений вы можете использовать Log.i("TAG", Thread.currentThread().getName()); и посмотреть 🙂

По моему опыту, эти обратные вызовы всегда возвращаются к потоку, отличному от UI. Вы пробовали Activity.runOnUiThread() чтобы убедиться, что ваш код работает в потоке пользовательского интерфейса? Вы по-прежнему будете использовать производительность, потому что для запуска этого кода требуется больше времени, но вы бы избежали некоторых из наиболее распространенных проблем с синхронизацией потоков.

В общем случае обратные вызовы будут возникать в потоке, в котором выполняется событие. Если вы зарегистрируете обратный вызов и начнете что-то играть в потоке, отличном от UI, тогда обратный вызов будет выполняться в потоке, отличном от UI. Однако Android не будет создавать новые потоки в фоновом режиме самостоятельно.

Все связанные с UI события должны происходить в потоке пользовательского интерфейса, так что вы можете gauarentee, что обратные вызовы обработчика кликов и т. Д. Будут возникать в потоке пользовательского интерфейса.

Как указал Aaron C, вы можете использовать Activity.runOnUiThread, чтобы заставить вас там что-то происходить.

Кроме того, AsyncTask может быть очень полезен для выполнения быстрой фоновой работы, когда вам нужно выполнить какой-либо этап завершения, который будет использоваться для потока uI.

Edit: Пример из комментариев.

 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(); } 

В этом примере функция callback onComplete будет запускаться из потока, отличного от UI. Поток будет завершен после завершения завершения.

Другое исключение – когда вы используете WebView. Когда javascript вызывает функцию Java, такой вызов не будет происходить в основном потоке

Что-то подобное возникло, когда я работал над API-интерфейсом. Как мы знаем, мы предоставляем обратный вызов для служб местоположения, чтобы мы получили уведомление, как только мы приобрели место. Поэтому я делал что-то в этом обратном вызове, который занимал много времени, как использование API-интерфейсов Geocoder.

Я был под впечатлением до этого, этот обратный вызов будет вызываться из другого потока и, таким образом, не будет выполняться в основном потоке пользовательского интерфейса. Но я вижу, это не так.

Итак, какой код, который я пишу в этом слушателе, будет выполняться в основном потоке.

Теперь то, что я не понимаю, так это, как им удается это сделать, используя функцию runOnUIThread() ???