Неявный выбор циклизатора во время построения обработчика может привести к ошибкам, при которых операции автоматически теряются (если Обработчик не ожидает новых задач и завершает работу), сбоям (если обработчик иногда создается в потоке без активного циклизатора) или условиям гонки, когда поток, с которым связан обработчик, не соответствует ожиданиям автора. Вместо этого используйте Executor или явно укажите Looper, используя Looper#getMainLooper , {link android.view.View#getHandler} или аналогичный. Если для совместимости требуется неявное локальное поведение потока, используйте новый обработчик (Looper.myLooper(), обратный вызов), чтобы читателям было понятно.
// Create an executor that executes tasks in the main thread. ExecutormainExecutor= ContextCompat.getMainExecutor(this);
// Execute a task in the main thread mainExecutor.execute(newRunnable() { @Override publicvoidrun() { // You code logic goes here. } });
Kotlin
// Create an executor that executes tasks in the main thread. val mainExecutor = ContextCompat.getMainExecutor(this)
// Execute a task in the main thread mainExecutor.execute { // You code logic goes here. }
2. Выполнение кода в фоновом потоке
Java
// Create an executor that executes tasks in a background thread. ScheduledExecutorService backgroundExecutor = Executors.newSingleThreadScheduledExecutor();
// Execute a task in the background thread. backgroundExecutor.execute(newRunnable() { @Override publicvoidrun() { // Your code logic goes here. } });
// Execute a task in the background thread after 3 seconds. backgroundExecutor.schedule(newRunnable() { @Override publicvoidrun() { // Your code logic goes here } }, 3, TimeUnit.SECONDS);
Kotlin
// Create an executor that executes tasks in a background thread. val backgroundExecutor: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
// Execute a task in the background thread. backgroundExecutor.execute { // Your code logic goes here. }
// Execute a task in the background thread after 3 seconds. backgroundExecutor.schedule({ // Your code logic goes here }, 3, TimeUnit.SECONDS)
Note: Remember to shut down the executor after using.
backgroundExecutor.shutdown(); // or backgroundExecutor.shutdownNow();
3. Execute code in a background thread and update UI on the main thread.
Java
// Create an executor that executes tasks in the main thread. ExecutormainExecutor= ContextCompat.getMainExecutor(this);
// Create an executor that executes tasks in a background thread. ScheduledExecutorServicebackgroundExecutor= Executors.newSingleThreadScheduledExecutor();
// Execute a task in the background thread. backgroundExecutor.execute(newRunnable() { @Override publicvoidrun() { // Your code logic goes here.
// Update UI on the main thread mainExecutor.execute(newRunnable() { @Override publicvoidrun() { // You code logic goes here. } }); } });
Kotlin
// Create an executor that executes tasks in the main thread. val mainExecutor: Executor = ContextCompat.getMainExecutor(this)
// Create an executor that executes tasks in a background thread. val backgroundExecutor = Executors.newSingleThreadScheduledExecutor()
// Execute a task in the background thread. backgroundExecutor.execute { // Your code logic goes here.
// Update UI on the main thread mainExecutor.execute { // You code logic goes here. } }
Solution 2: Specify a Looper explicitly by using one of the following constructors.
// Create a background thread that has a Looper HandlerThreadhandlerThread=newHandlerThread("HandlerThread"); handlerThread.start();
// Create a handler to execute tasks in the background thread. HandlerbackgroundHandler=newHandler(handlerThread.getLooper());
Kotlin
// Create a background thread that has a Looper valhandlerThread= HandlerThread("HandlerThread") handlerThread.start()
// Create a handler to execute tasks in the background thread. valbackgroundHandler= Handler(handlerThread.looper)
2.2. Обработчик с циклом и обработчиком.Обратный вызов
Java
// Create a background thread that has a Looper HandlerThreadhandlerThread=newHandlerThread("HandlerThread"); handlerThread.start();
// Create a handler to execute taks in the background thread. HandlerbackgroundHandler=newHandler(handlerThread.getLooper(), newHandler.Callback() { @Override publicbooleanhandleMessage(@NonNull Message message) { // Your code logic goes here. returntrue; } });
Kotlin
// Create a background thread that has a Looper valhandlerThread= HandlerThread("HandlerThread") handlerThread.start()
// Create a handler to execute taks in the background thread. valbackgroundHandler= Handler(handlerThread.looper, Handler.Callback { // Your code logic goes here. true })
Примечание: Не забудьте освободить поток после использования.
handlerThread.quit(); // or handlerThread.quitSafely();
3. Выполните код в фоновом потоке и обновите пользовательский интерфейс в основном потоке.
Java
// Create a handler to execute code in the main thread HandlermainHandler=newHandler(Looper.getMainLooper());
// Create a background thread that has a Looper HandlerThreadhandlerThread=newHandlerThread("HandlerThread"); handlerThread.start();
// Create a handler to execute in the background thread HandlerbackgroundHandler=newHandler(handlerThread.getLooper(), newHandler.Callback() { @Override publicbooleanhandleMessage(@NonNull Message message) { // Your code logic goes here.
// Update UI on the main thread. mainHandler.post(newRunnable() { @Override publicvoidrun() {
} });
returntrue; } });
Kotlin
// Create a handler to execute code in the main thread valmainHandler= Handler(Looper.getMainLooper())
// Create a background thread that has a Looper valhandlerThread= HandlerThread("HandlerThread") handlerThread.start()
// Create a handler to execute in the background thread valbackgroundHandler= Handler(handlerThread.looper, Handler.Callback { // Your code logic goes here.
// Update UI on the main thread. mainHandler.post {
} true })
Ответ 3
Если вы хотите избежать проверки null в Kotlin (? или !!), вы можете использовать, Looper.getMainLooper() если ваш Handler работает с какой-либо функцией, связанной с пользовательским интерфейсом, например, с этим: