Основы 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");
}
}
7 ответов
ни один из них не является точно таким же, хотя все они будут иметь одинаковый чистый эффект.
разница между первым и вторым заключается в том, что если вам случится быть on основной поток приложения при выполнении кода, первый (runOnUiThread()
) будет выполнять Runnable
немедленно. Второй (post()
) всегда ставит Runnable
в конце очереди событий, даже если вы уже в главном потоке приложения.
третий, предполагая, что вы создаете и выполняете экземпляр BackgroundTask
, будет тратить много времени на захват потока из пула потоков, чтобы выполнить no-op , прежде чем в конечном итоге делает то, что составляет post()
. Это, безусловно, наименее эффективно из трех. Использовать AsyncTask
если у вас действительно есть работа в фоновом потоке, а не только за использование onPostExecute()
.
Мне нравится один из комментарий ГЭС, его можно использовать везде без любого параметра:
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
существует четвертый способ использования Handler
new Handler().post(new Runnable() {
@Override
public void run() {
// Code here will run in UI thread
}
});
ответ 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);
Если вам нужно использовать во фрагменте, вы должны использовать
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");
}
});
потому что в некоторых ситуациях, таких как фрагмент пейджера
привет, ребята, это основной вопрос, который я говорю
использовать проводник
new Handler().post(new Runnable() {
@Override
public void run() {
// Code here will run in UI thread
}
});
начиная с Android P вы можете использовать getMainExecutor()
:
getMainExecutor().execute(new Runnable() {
@Override public void run() {
// Code will run on the main thread
}
});
С документы для разработчиков Android:
возвращает исполнитель, который будет выполнять поставленные в очередь задачи в основном потоке, связанном с этим контекстом. Это поток, используемый для отправки вызовов компонентам приложения (действия, службы и т. д.).
С CommonsBlog:
вы можете вызвать getMainExecutor () в контексте, чтобы получить Исполнитель, который будет выполнять свои задания в основном потоке приложения. Есть и другие способы выполнения этого, используя Looper и пользовательскую реализацию исполнителя, но это проще.