Страница 1 из 2

Урок 85. Еще несколько способов выполнения кода в UI-потоке

Добавлено: 06 июн 2012, 23:00
damager82
В этом уроке:
- рассмотрим еще пару способов запуска Runnable в UI-потоке 


Click here to read this article!

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 07 июн 2012, 17:52
KamiSempai
Первые два похожи и отправляют Runnable на немедленную обработку. Я не знаю в чем их принципиальное отличие. Если у вас есть соображения на этот счет, пишите на форуме в ветке этого урока.
Привожу исходный код:

Код: Выделить всё

    private final Handler mHandler = new Handler();

    public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }
В общем ни чего сложного. Если мы не в своем потоке используем заранее созданный Handler (кстати, ето единственное место, где он используется :D), если в своем потоке, в лоб запускаем 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);
    }
Я так понимаю, mAttachInfo - это интерфейс, который создается в момент расположения View на экране, причем создается не в View а передается в качестве параметра.
В случае с ViewRoot все еще более запутано. Времени нет разбираться, на тренировку пора :)

PS: View.postDelayed(Runnable, long) аналогичен View.post(Runnable, long).

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 08 июн 2012, 09:22
damager82
Код я тоже смотрел.
Я имею ввиду разницу с точки зрения использования двух этих методов для разраба. Как решить, какой юзать. И в чем разница по функционалу.

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 08 июн 2012, 18:01
KamiSempai
Если брать пример из урока, разницы, на мой взгляд, никакой. Все 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 с задержкой, обратно.
Погорячился немного. Или я сам из этих? :D

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 15 июл 2012, 11:56
Jane
Не совсем поняла.
Ui-поток - это наш основной поток. В нём мы создаём Handler, следовательно, этот Handler привязан к основному потоку. А из другого потока мы передаём в ui-поток через Handler сообщения.
Если не использовать Handler, а три метода из этого урока, то мы опять же влияем на основной поток, но только без Handler.
Да?

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 17 июл 2012, 10:59
damager82
Jane писал(а):Не совсем поняла.
Ui-поток - это наш основной поток. В нём мы создаём Handler, следовательно, этот Handler привязан к основному потоку. А из другого потока мы передаём в ui-поток через Handler сообщения.
Если не использовать Handler, а три метода из этого урока, то мы опять же влияем на основной поток, но только без Handler.
Да?
Просто здесь реализация Handler скрыта внутри этих методов и нам не надо думать об этом. Но механизм тот же.

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 29 авг 2012, 10:30
Artemko
а как выполнять этот кусок кода например каждую минуту?

Код: Выделить всё

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-пот

Добавлено: 29 авг 2012, 10:31
rezak90
Artemko писал(а):а как выполнять этот кусок кода например каждую минуту?

Код: Выделить всё

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();
http://developer.android.com/intl/ru/re ... rTask.html

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 29 авг 2012, 10:43
Artemko
так будет правильно?

Код: Выделить всё

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-пот

Добавлено: 29 авг 2012, 10:47
rezak90
run() в TimerTask'e это уже отдельный поток, зачем в отдельном потоке городить ещё один поток)))

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 29 авг 2012, 10:56
Artemko
а как сделать нормально?
у меня всё подчеркивает красным если я удаляю run()

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 29 авг 2012, 11:03
neoksi

Код: Выделить всё

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-пот

Добавлено: 14 мар 2015, 20:00
d.u.a.l
А почему в уроке №80 код

Код: Выделить всё

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-элементу вызывал ошибку Only the original thread that created a view hierarchy can touch its views.
А код, который тоже обращается к аналогичному 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();
  }
работает???

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 27 июл 2015, 11:06
K_Vladimir
Всем доброго дня!
Выходит что НЕЛЬЗЯ вызывать 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-пот

Добавлено: 28 июл 2015, 18:05
rePlay
K_Vladimir Можно, просто ты нагрузил UI-поток, и поэтому экран не обновляется. Экран начнёт обновляться после отработки метода OnCreate (предполагаю, что в нем тестировал код).

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 29 июл 2015, 01:08
K_Vladimir
rePlay писал(а):K_Vladimir Можно, просто ты нагрузил UI-поток, и поэтому экран не обновляется. Экран начнёт обновляться после отработки метода OnCreate (предполагаю, что в нем тестировал код).
Попробовал вынести из onCreate. Через кнопку, срабатывают только runn2 и runn3.
Я думаю что вызывать этот метод из основного потока просто нет никакого смысла

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 29 июл 2015, 03:29
rePlay
K_Vladimir писал(а):
rePlay писал(а):K_Vladimir Можно, просто ты нагрузил UI-поток, и поэтому экран не обновляется. Экран начнёт обновляться после отработки метода OnCreate (предполагаю, что в нем тестировал код).
Попробовал вынести из onCreate. Через кнопку, срабатывают только runn2 и runn3.
Я думаю что вызывать этот метод из основного потока просто нет никакого смысла
Неправильный вывод. Я же говорю, что ты загрузил UI-поток всякими sleep'ами, из-за чего он не обновляется. Закомментируй
tvInfo.post(runn2); и появится run1. Нужно просто понимать, как отрабатывает твое приложение.

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 29 июл 2015, 10:53
K_Vladimir
rePlay писал(а):
K_Vladimir писал(а):
rePlay писал(а):K_Vladimir Можно, просто ты нагрузил UI-поток, и поэтому экран не обновляется. Экран начнёт обновляться после отработки метода OnCreate (предполагаю, что в нем тестировал код).
Попробовал вынести из onCreate. Через кнопку, срабатывают только runn2 и runn3.
Я думаю что вызывать этот метод из основного потока просто нет никакого смысла
Неправильный вывод. Я же говорю, что ты загрузил UI-поток всякими sleep'ами, из-за чего он не обновляется. Закомментируй
tvInfo.post(runn2); и появится run1. Нужно просто понимать, как отрабатывает твое приложение.
Вы абсолютно правы. Теперь вижу, что runn1 отрабатывает из основного потока. Да, это важно для понимания всего механизма работы приложения. Спасибо.

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 22 авг 2015, 11:45
Turkovsky
damager82 писал(а): Первые два похожи и отправляют Runnable на немедленную обработку. Я не знаю в чем их принципиальное отличие. Если у вас есть соображения на этот счет, пишите на форуме в ветке этого урока.
Метод runOnUiThread принадлежит активности, а post принадлежит конкретному виджету.
Собственно, я Runnable-объекты не выносил, а прописывал сразу:

Код: Выделить всё

MainActivity.this.runOnUiThread(new Runnable()
{
   @Override
   public void run()
   {
      MainActivity.this.buttonOne.setText("text1");
      MainActivity.this.textViewOne.setText("text2");
   }
});
Таким образом, можно обращаться к нескольким разным виджетам, чего в post, насколько знаю, делать нельзя.

Re: Урок 85. Еще несколько способов выполнения кода в UI-пот

Добавлено: 26 фев 2018, 06:27
donec
Подскажите почему в классе MyTimerTask (класс в отдельном файле) не видно textView из MainActivity? Саму MainActivity видит.
20.png
20.png (34.84 КБ) 13215 просмотров