Урок 85. Еще несколько способов выполнения кода в UI-потоке
Урок 85. Еще несколько способов выполнения кода в UI-потоке
В этом уроке:
- рассмотрим еще пару способов запуска Runnable в UI-потоке
Click here to read this article!
- рассмотрим еще пару способов запуска Runnable в UI-потоке
Click here to read this article!
Последний раз редактировалось damager82 20 май 2017, 20:08, всего редактировалось 5 раз.
- KamiSempai
- Сообщения: 1339
- Зарегистрирован: 17 фев 2012, 21:23
- Откуда: Мордор
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
Привожу исходный код:Первые два похожи и отправляют Runnable на немедленную обработку. Я не знаю в чем их принципиальное отличие. Если у вас есть соображения на этот счет, пишите на форуме в ветке этого урока.
Код: Выделить всё
private final Handler mHandler = new Handler();
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
С View на много сложнее:
Код: Выделить всё
public boolean post(Runnable action) {
Handler handler;
if (mAttachInfo != null) {
handler = mAttachInfo.mHandler;
} else {
// Assume that post will succeed later
ViewRoot.getRunQueue().post(action);
return true;
}
return handler.post(action);
}
В случае с ViewRoot все еще более запутано. Времени нет разбираться, на тренировку пора
PS: View.postDelayed(Runnable, long) аналогичен View.post(Runnable, long).
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.
Хватит таскать макулатуру на тренировку! Используй T Note.
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
Код я тоже смотрел.
Я имею ввиду разницу с точки зрения использования двух этих методов для разраба. Как решить, какой юзать. И в чем разница по функционалу.
Я имею ввиду разницу с точки зрения использования двух этих методов для разраба. Как решить, какой юзать. И в чем разница по функционалу.
- KamiSempai
- Сообщения: 1339
- Зарегистрирован: 17 фев 2012, 21:23
- Откуда: Мордор
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
Если брать пример из урока, разницы, на мой взгляд, никакой. Все Runnable смирно встают в очередь и ждут когда впереди стоящие сообщения отработают.
Однако, если взять View не расположенную на форме (например, создать: v = new View(this)), Runnable выполнен не будет. По крайней мере у меня он не выполнился.
Видимо ViewRoot не очень хорошо справляется с этой задачей. Следовательно, если есть шанс наткнуться на View не расположенную на экране лучше использовать runOnUiThread().
Недостаток runOnUiThread() - нет возможности запускать Runnable с задержкой. Но если подумать, кому, кроме как извращенцу, понадобится обновлять экранные компоненты с задержкой?
Еще одна особенность runOnUiThread(), если вызвать его в UI потоке, Runnable выполнится тут-же, не вставая в очередь.
Например, мы вызываем runOnUiThread(runn1), за ним сразу tvInfo.post(runn2), но внутри runn1 у нас runOnUiThread(runn3). Порядок выполнения будет: runn1, runn3, runn2.
В случае с tvInfo.post(runn3) такой перестановки не произойдет.
Вывод который я лично для себя сделал: По возможности стараться использовать runOnUiThread(), так как задача будет выполнена 100%. Если нет доступа к Activity, например в другом классе, но есть ссылка на View, которую нужно изменить, можно смело использовать View.post().
UPD [09.06.2012]: Беру свои слова, про извращенцев и обновление UI с задержкой, обратно.
Погорячился немного. Или я сам из этих?
Однако, если взять View не расположенную на форме (например, создать: v = new View(this)), Runnable выполнен не будет. По крайней мере у меня он не выполнился.
Видимо ViewRoot не очень хорошо справляется с этой задачей. Следовательно, если есть шанс наткнуться на View не расположенную на экране лучше использовать runOnUiThread().
Недостаток runOnUiThread() - нет возможности запускать Runnable с задержкой. Но если подумать, кому, кроме как извращенцу, понадобится обновлять экранные компоненты с задержкой?
Еще одна особенность runOnUiThread(), если вызвать его в UI потоке, Runnable выполнится тут-же, не вставая в очередь.
Например, мы вызываем runOnUiThread(runn1), за ним сразу tvInfo.post(runn2), но внутри runn1 у нас runOnUiThread(runn3). Порядок выполнения будет: runn1, runn3, runn2.
В случае с tvInfo.post(runn3) такой перестановки не произойдет.
Вывод который я лично для себя сделал: По возможности стараться использовать runOnUiThread(), так как задача будет выполнена 100%. Если нет доступа к Activity, например в другом классе, но есть ссылка на View, которую нужно изменить, можно смело использовать View.post().
UPD [09.06.2012]: Беру свои слова, про извращенцев и обновление UI с задержкой, обратно.
Погорячился немного. Или я сам из этих?
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.
Хватит таскать макулатуру на тренировку! Используй T Note.
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
Не совсем поняла.
Ui-поток - это наш основной поток. В нём мы создаём Handler, следовательно, этот Handler привязан к основному потоку. А из другого потока мы передаём в ui-поток через Handler сообщения.
Если не использовать Handler, а три метода из этого урока, то мы опять же влияем на основной поток, но только без Handler.
Да?
Ui-поток - это наш основной поток. В нём мы создаём Handler, следовательно, этот Handler привязан к основному потоку. А из другого потока мы передаём в ui-поток через Handler сообщения.
Если не использовать Handler, а три метода из этого урока, то мы опять же влияем на основной поток, но только без Handler.
Да?
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
Просто здесь реализация Handler скрыта внутри этих методов и нам не надо думать об этом. Но механизм тот же.Jane писал(а):Не совсем поняла.
Ui-поток - это наш основной поток. В нём мы создаём Handler, следовательно, этот Handler привязан к основному потоку. А из другого потока мы передаём в ui-поток через Handler сообщения.
Если не использовать Handler, а три метода из этого урока, то мы опять же влияем на основной поток, но только без Handler.
Да?
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
а как выполнять этот кусок кода например каждую минуту?
Код: Выделить всё
Thread t = new Thread(new Runnable() {
public void run() {
try {
TimeUnit.SECONDS.sleep(2);
runOnUiThread(runn1);
TimeUnit.SECONDS.sleep(1);
tvInfo.postDelayed(runn3, 2000);
tvInfo.post(runn2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
http://developer.android.com/intl/ru/re ... rTask.htmlArtemko писал(а):а как выполнять этот кусок кода например каждую минуту?Код: Выделить всё
Thread t = new Thread(new Runnable() { public void run() { try { TimeUnit.SECONDS.sleep(2); runOnUiThread(runn1); TimeUnit.SECONDS.sleep(1); tvInfo.postDelayed(runn3, 2000); tvInfo.post(runn2); } catch (InterruptedException e) { e.printStackTrace(); } } }); t.start();
R.id.team
Политика на форуме запрещена
Политика на форуме запрещена
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
так будет правильно?
Код: Выделить всё
myTimer.schedule(new TimerTask() {
@Override
public void run() {
t.start();
}
}, 0L, 60L * 1000);
Thread t = new Thread(new Runnable() {
public void run() {
try {
TimeUnit.SECONDS.sleep(2);
runOnUiThread(runn1);
TimeUnit.SECONDS.sleep(1);
tvInfo.postDelayed(runn3, 2000);
tvInfo.post(runn2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
run() в TimerTask'e это уже отдельный поток, зачем в отдельном потоке городить ещё один поток)))
R.id.team
Политика на форуме запрещена
Политика на форуме запрещена
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
а как сделать нормально?
у меня всё подчеркивает красным если я удаляю run()
у меня всё подчеркивает красным если я удаляю run()
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
Код: Выделить всё
myTimer.schedule(new TimerTask() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(2);
runOnUiThread(runn1);
TimeUnit.SECONDS.sleep(1);
tvInfo.postDelayed(runn3, 2000);
tvInfo.post(runn2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 0L, 60L * 1000);
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
А почему в уроке №80 код
в результате обращения из другого потока ко View-элементу вызывал ошибку Only the original thread that created a view hierarchy can touch its views.
А код, который тоже обращается к аналогичному View (TextView) из другого потока в данном уроке
работает???
Код: Выделить всё
public void onclick(View v) {
switch (v.getId()) {
case R.id.btnStart:
Thread t = new Thread(new Runnable() {
public void run() {
for (int i = 1; i <= 10; i++) {
// долгий процесс
downloadFile();
// обновляем TextView
tvInfo.setText("Закачано файлов: " + i);
// пишем лог
Log.d(LOG_TAG, "i = " + i);
}
}
});
t.start();
break;
case R.id.btnTest:
Log.d(LOG_TAG, "test");
break;
default:
break;
}
}
А код, который тоже обращается к аналогичному View (TextView) из другого потока в данном уроке
Код: Выделить всё
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tvInfo = (TextView) findViewById(R.id.tvInfo);
Thread t = new Thread(new Runnable() {
public void run() {
try {
TimeUnit.SECONDS.sleep(2);
runOnUiThread(runn1);
TimeUnit.SECONDS.sleep(1);
tvInfo.postDelayed(runn3, 2000);
tvInfo.post(runn2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
-
- Сообщения: 36
- Зарегистрирован: 28 июн 2015, 03:13
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
Всем доброго дня!
Выходит что НЕЛЬЗЯ вызывать runOnUiThread(runn1); в основном потоке.
Я попробовал убрать создание нового потока и вызвать все наши испытуемые методы из основного потока.
В результате на экране отобразился только runn2 и runn3. Т.е. runOnUiThread(runn1); не сработал.
Выходит что НЕЛЬЗЯ вызывать runOnUiThread(runn1); в основном потоке.
Я попробовал убрать создание нового потока и вызвать все наши испытуемые методы из основного потока.
В результате на экране отобразился только runn2 и runn3. Т.е. runOnUiThread(runn1); не сработал.
Код: Выделить всё
try {
TimeUnit.SECONDS.sleep(2);
runOnUiThread(runn1);
TimeUnit.SECONDS.sleep(1);
tvInfo.postDelayed(runn3, 2000);
tvInfo.post(runn2);
} catch (InterruptedException e) {
e.printStackTrace();
}
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
K_Vladimir Можно, просто ты нагрузил UI-поток, и поэтому экран не обновляется. Экран начнёт обновляться после отработки метода OnCreate (предполагаю, что в нем тестировал код).
-
- Сообщения: 36
- Зарегистрирован: 28 июн 2015, 03:13
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
Попробовал вынести из onCreate. Через кнопку, срабатывают только runn2 и runn3.rePlay писал(а):K_Vladimir Можно, просто ты нагрузил UI-поток, и поэтому экран не обновляется. Экран начнёт обновляться после отработки метода OnCreate (предполагаю, что в нем тестировал код).
Я думаю что вызывать этот метод из основного потока просто нет никакого смысла
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
Неправильный вывод. Я же говорю, что ты загрузил UI-поток всякими sleep'ами, из-за чего он не обновляется. ЗакомментируйK_Vladimir писал(а):Попробовал вынести из onCreate. Через кнопку, срабатывают только runn2 и runn3.rePlay писал(а):K_Vladimir Можно, просто ты нагрузил UI-поток, и поэтому экран не обновляется. Экран начнёт обновляться после отработки метода OnCreate (предполагаю, что в нем тестировал код).
Я думаю что вызывать этот метод из основного потока просто нет никакого смысла
tvInfo.post(runn2); и появится run1. Нужно просто понимать, как отрабатывает твое приложение.
-
- Сообщения: 36
- Зарегистрирован: 28 июн 2015, 03:13
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
Вы абсолютно правы. Теперь вижу, что runn1 отрабатывает из основного потока. Да, это важно для понимания всего механизма работы приложения. Спасибо.rePlay писал(а):Неправильный вывод. Я же говорю, что ты загрузил UI-поток всякими sleep'ами, из-за чего он не обновляется. ЗакомментируйK_Vladimir писал(а):Попробовал вынести из onCreate. Через кнопку, срабатывают только runn2 и runn3.rePlay писал(а):K_Vladimir Можно, просто ты нагрузил UI-поток, и поэтому экран не обновляется. Экран начнёт обновляться после отработки метода OnCreate (предполагаю, что в нем тестировал код).
Я думаю что вызывать этот метод из основного потока просто нет никакого смысла
tvInfo.post(runn2); и появится run1. Нужно просто понимать, как отрабатывает твое приложение.
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
Метод runOnUiThread принадлежит активности, а post принадлежит конкретному виджету.damager82 писал(а): Первые два похожи и отправляют Runnable на немедленную обработку. Я не знаю в чем их принципиальное отличие. Если у вас есть соображения на этот счет, пишите на форуме в ветке этого урока.
Собственно, я Runnable-объекты не выносил, а прописывал сразу:
Код: Выделить всё
MainActivity.this.runOnUiThread(new Runnable()
{
@Override
public void run()
{
MainActivity.this.buttonOne.setText("text1");
MainActivity.this.textViewOne.setText("text2");
}
});
Re: Урок 85. Еще несколько способов выполнения кода в UI-пот
Подскажите почему в классе MyTimerTask (класс в отдельном файле) не видно textView из MainActivity? Саму MainActivity видит.