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