Основы Android: запуск кода в потоке пользовательского интерфейса
С точки зрения запуска кода в потоке пользовательского интерфейса существует ли разница между:
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
или
MainActivity.this.myView.post(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
и
private class BackgroundTask extends AsyncTask<String, Void, Bitmap> {
protected void onPostExecute(Bitmap result) {
Log.d("UI thread", "I am the UI thread");
}
}
Ответы
Ответ 1
Ни один из них не является тем же самым, хотя все они будут иметь одинаковый сетевой эффект.
Разница между первой и второй заключается в том, что если вы выполняете основной поток приложения при выполнении кода, первый (runOnUiThread()
) немедленно выполнит Runnable
. Второй (post()
) всегда помещает Runnable
в конец очереди событий, даже если вы уже находитесь в главном потоке приложения.
Третий, предполагая, что вы создаете и выполняете экземпляр BackgroundTask
, будет тратить много времени на захват потока из пула потоков, чтобы выполнить по умолчанию no-op doInBackground()
, прежде чем, в конце концов, сделать какие суммы до post()
. Это, безусловно, наименее эффективный из трех. Используйте AsyncTask
, если на самом деле у вас есть работа в фоновом потоке, а не только на использование onPostExecute()
.
Ответ 2
Мне нравится комментарий HPP, его можно использовать где угодно без каких-либо параметров:
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
Ответ 3
Существует четвертый способ использования Handler
new Handler().post(new Runnable() {
@Override
public void run() {
// Code here will run in UI thread
}
});
Ответ 4
Ответ Pomber приемлем, однако я не большой поклонник создания новых объектов повторно. Лучшими решениями всегда являются те, которые пытаются уменьшить волну памяти. Да, есть сбор мусора, но сохранение памяти в мобильном устройстве находится в пределах передового опыта.
Код ниже обновляет TextView в сервисе.
TextViewUpdater textViewUpdater = new TextViewUpdater();
Handler textViewUpdaterHandler = new Handler(Looper.getMainLooper());
private class TextViewUpdater implements Runnable{
private String txt;
@Override
public void run() {
searchResultTextView.setText(txt);
}
public void setText(String txt){
this.txt = txt;
}
}
Его можно использовать в любом месте:
textViewUpdater.setText("Hello");
textViewUpdaterHandler.post(textViewUpdater);
Ответ 5
Если вам нужно использовать в Фрагменте, вы должны использовать
private Context context;
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
((MainActivity)context).runOnUiThread(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
вместо
getActivity().runOnUiThread(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
Потому что в некоторой ситуации, такой как фрагмент пейджера, будет исключение с нулевым указателем
Ответ 6
С Android P вы можете использовать getMainExecutor()
:
getMainExecutor().execute(new Runnable() {
@Override public void run() {
// Code will run on the main thread
}
});
Из Android-разработчиков:
Верните Исполнителя, который будет запускать заданные задачи в основном потоке, связанном с этим контекстом. Это поток, используемый для отправки вызовов компонентам приложения (действия, службы и т.д.).
Из CommonsBlog:
Вы можете вызвать getMainExecutor() в Контексте, чтобы получить Исполнитель, который выполнит свои задания в главном потоке приложения. Существуют и другие способы достижения этого, используя Looper и пользовательскую реализацию Executor, но это проще.
Ответ 7
привет, ребята, это основной вопрос в любом случае, я говорю
использовать обработчик
new Handler().post(new Runnable() {
@Override
public void run() {
// Code here will run in UI thread
}
});
Ответ 8
MainActivity.this.myView.post(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
работает для меня. Спасибо!