Google Android - это несложно

Добро пожаловать на форум сайта startandroid.ru
Текущее время: 25 фев 2017, 13:09

Часовой пояс: UTC + 4 часа




Начать новую тему Ответить на тему  [ Сообщений: 19 ] 
Автор Сообщение
СообщениеДобавлено: 07 июн 2012, 00:00 
Администратор
Аватар пользователя

Зарегистрирован: 07 янв 2012, 12:32
Сообщений: 1319
Благодарил (а): 0 раз.
Поблагодарили: 69 раз.
В этом уроке:

- рассмотрим еще пару способов запуска Runnable в UI-потоке

Click here to read this article!

_________________
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение


Последний раз редактировалось damager82 07 янв 2017, 19:30, всего редактировалось 4 раз(а).

Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 07 июн 2012, 18:52 
Аватар пользователя

Зарегистрирован: 17 фев 2012, 22:23
Сообщений: 1338
Откуда: Мордор
Благодарил (а): 16 раз.
Поблагодарили: 161 раз.
Цитата:
Первые два похожи и отправляют Runnable на немедленную обработку. Я не знаю в чем их принципиальное отличие. Если у вас есть соображения на этот счет, пишите на форуме в ветке этого урока.
Привожу исходный код:
Код: [ Загрузить ] [ Скрыть ]
Using Java Syntax Highlighting
  1.     private final Handler mHandler = new Handler();
  2.  
  3.     public final void runOnUiThread(Runnable action) {
  4.         if (Thread.currentThread() != mUiThread) {
  5.             mHandler.post(action);
  6.         } else {
  7.             action.run();
  8.         }
  9.     }
В общем ни чего сложного. Если мы не в своем потоке используем заранее созданный Handler (кстати, ето единственное место, где он используется :D), если в своем потоке, в лоб запускаем run.

С View на много сложнее:
Код: [ Загрузить ] [ Скрыть ]
Using Java Syntax Highlighting
  1.     public boolean post(Runnable action) {
  2.         Handler handler;
  3.         if (mAttachInfo != null) {
  4.             handler = mAttachInfo.mHandler;
  5.         } else {
  6.             // Assume that post will succeed later
  7.             ViewRoot.getRunQueue().post(action);
  8.             return true;
  9.         }
  10.         return handler.post(action);
  11.     }
Я так понимаю, mAttachInfo - это интерфейс, который создается в момент расположения View на экране, причем создается не в View а передается в качестве параметра.
В случае с ViewRoot все еще более запутано. Времени нет разбираться, на тренировку пора :)

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

_________________
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 08 июн 2012, 10:22 
Администратор
Аватар пользователя

Зарегистрирован: 07 янв 2012, 12:32
Сообщений: 1319
Благодарил (а): 0 раз.
Поблагодарили: 69 раз.
Код я тоже смотрел.
Я имею ввиду разницу с точки зрения использования двух этих методов для разраба. Как решить, какой юзать. И в чем разница по функционалу.

_________________
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 08 июн 2012, 19:01 
Аватар пользователя

Зарегистрирован: 17 фев 2012, 22:23
Сообщений: 1338
Откуда: Мордор
Благодарил (а): 16 раз.
Поблагодарили: 161 раз.
Если брать пример из урока, разницы, на мой взгляд, никакой. Все 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

_________________
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 15 июл 2012, 12:56 

Зарегистрирован: 11 июл 2012, 13:30
Сообщений: 6
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Не совсем поняла.
Ui-поток - это наш основной поток. В нём мы создаём Handler, следовательно, этот Handler привязан к основному потоку. А из другого потока мы передаём в ui-поток через Handler сообщения.
Если не использовать Handler, а три метода из этого урока, то мы опять же влияем на основной поток, но только без Handler.
Да?


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 17 июл 2012, 11:59 
Администратор
Аватар пользователя

Зарегистрирован: 07 янв 2012, 12:32
Сообщений: 1319
Благодарил (а): 0 раз.
Поблагодарили: 69 раз.
Jane писал(а):
Не совсем поняла.
Ui-поток - это наш основной поток. В нём мы создаём Handler, следовательно, этот Handler привязан к основному потоку. А из другого потока мы передаём в ui-поток через Handler сообщения.
Если не использовать Handler, а три метода из этого урока, то мы опять же влияем на основной поток, но только без Handler.
Да?

Просто здесь реализация Handler скрыта внутри этих методов и нам не надо думать об этом. Но механизм тот же.

_________________
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 29 авг 2012, 11:30 

Зарегистрирован: 16 июл 2012, 16:09
Сообщений: 26
Благодарил (а): 1 раз.
Поблагодарили: 0 раз.
а как выполнять этот кусок кода например каждую минуту?
Код: [ Загрузить ] [ Скрыть ]
Using Java Syntax Highlighting
  1. Thread t = new Thread(new Runnable() {
  2.             public void run() {
  3.               try {
  4.                 TimeUnit.SECONDS.sleep(2);
  5.                 runOnUiThread(runn1);
  6.                 TimeUnit.SECONDS.sleep(1);
  7.                 tvInfo.postDelayed(runn3, 2000);
  8.                 tvInfo.post(runn2);
  9.               } catch (InterruptedException e) {
  10.                 e.printStackTrace();
  11.               }
  12.             }
  13.           });
  14.           t.start();


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 29 авг 2012, 11:31 
Аватар пользователя

Зарегистрирован: 26 июн 2012, 14:22
Сообщений: 3422
Откуда: UA
Благодарил (а): 11 раз.
Поблагодарили: 244 раз.
Artemko писал(а):
а как выполнять этот кусок кода например каждую минуту?
Код: [ Загрузить ] [ Скрыть ]
Using Java Syntax Highlighting
  1. Thread t = new Thread(new Runnable() {
  2.             public void run() {
  3.               try {
  4.                 TimeUnit.SECONDS.sleep(2);
  5.                 runOnUiThread(runn1);
  6.                 TimeUnit.SECONDS.sleep(1);
  7.                 tvInfo.postDelayed(runn3, 2000);
  8.                 tvInfo.post(runn2);
  9.               } catch (InterruptedException e) {
  10.                 e.printStackTrace();
  11.               }
  12.             }
  13.           });
  14.           t.start();

http://developer.android.com/intl/ru/reference/java/util/TimerTask.html

_________________
R.id.team
Политика на форуме запрещена


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 29 авг 2012, 11:43 

Зарегистрирован: 16 июл 2012, 16:09
Сообщений: 26
Благодарил (а): 1 раз.
Поблагодарили: 0 раз.
так будет правильно?
Код: [ Загрузить ] [ Скрыть ]
Using Java Syntax Highlighting
  1. myTimer.schedule(new TimerTask() {
  2.                         @Override
  3.                         public void run() {
  4.                                 t.start();
  5.                         }              
  6.         }, 0L, 60L * 1000);
  7.        
  8.         Thread t = new Thread(new Runnable() {
  9.             public void run() {
  10.               try {
  11.                 TimeUnit.SECONDS.sleep(2);
  12.                 runOnUiThread(runn1);
  13.                 TimeUnit.SECONDS.sleep(1);
  14.                 tvInfo.postDelayed(runn3, 2000);
  15.                 tvInfo.post(runn2);
  16.               } catch (InterruptedException e) {
  17.                 e.printStackTrace();
  18.               }
  19.             }
  20.           });
  21.  


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 29 авг 2012, 11:47 
Аватар пользователя

Зарегистрирован: 26 июн 2012, 14:22
Сообщений: 3422
Откуда: UA
Благодарил (а): 11 раз.
Поблагодарили: 244 раз.
run() в TimerTask'e это уже отдельный поток, зачем в отдельном потоке городить ещё один поток)))

_________________
R.id.team
Политика на форуме запрещена


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 29 авг 2012, 11:56 

Зарегистрирован: 16 июл 2012, 16:09
Сообщений: 26
Благодарил (а): 1 раз.
Поблагодарили: 0 раз.
а как сделать нормально?
у меня всё подчеркивает красным если я удаляю run()


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 29 авг 2012, 12:03 
Аватар пользователя

Зарегистрирован: 26 июл 2012, 11:42
Сообщений: 712
Благодарил (а): 6 раз.
Поблагодарили: 18 раз.
Код: [ Загрузить ] [ Скрыть ]
Using Java Syntax Highlighting
  1. myTimer.schedule(new TimerTask() {
  2.                         @Override
  3.                         public void run() {
  4.         try {
  5.                 TimeUnit.SECONDS.sleep(2);
  6.                 runOnUiThread(runn1);
  7.                 TimeUnit.SECONDS.sleep(1);
  8.                 tvInfo.postDelayed(runn3, 2000);
  9.                 tvInfo.post(runn2);
  10.               } catch (InterruptedException e) {
  11.                 e.printStackTrace();
  12.               }
  13.                         }              
  14.         }, 0L, 60L * 1000);
  15.        
  16.  
  17.  


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 14 мар 2015, 21:00 

Зарегистрирован: 14 мар 2015, 20:56
Сообщений: 2
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
А почему в уроке №80 код
Код: [ Загрузить ] [ Скрыть ]
  1. public void onclick(View v) { 
  2.     switch (v.getId()) { 
  3.     case R.id.btnStart: 
  4.       Thread t = new Thread(new Runnable() { 
  5.         public void run() { 
  6.           for (int i = 1; i <= 10; i++) { 
  7.             // долгий процесс 
  8.             downloadFile(); 
  9.             // обновляем TextView 
  10.            tvInfo.setText("Закачано файлов: " + i); 
  11.             // пишем лог 
  12.             Log.d(LOG_TAG, "i = " + i); 
  13.           } 
  14.         } 
  15.       }); 
  16.       t.start(); 
  17.       break; 
  18.     case R.id.btnTest: 
  19.       Log.d(LOG_TAG, "test"); 
  20.       break; 
  21.     default: 
  22.       break; 
  23.     } 
  24.   } 

в результате обращения из другого потока ко View-элементу вызывал ошибку Only the original thread that created a view hierarchy can touch its views.
А код, который тоже обращается к аналогичному View (TextView) из другого потока в данном уроке
Код: [ Загрузить ] [ Скрыть ]
  1. public void onCreate(Bundle savedInstanceState) { 
  2.     super.onCreate(savedInstanceState); 
  3.     setContentView(R.layout.main); 
  4.  
  5.     tvInfo = (TextView) findViewById(R.id.tvInfo); 
  6.  
  7.     Thread t = new Thread(new Runnable() { 
  8.       public void run() { 
  9.         try { 
  10.           TimeUnit.SECONDS.sleep(2); 
  11.           runOnUiThread(runn1); 
  12.           TimeUnit.SECONDS.sleep(1); 
  13.           tvInfo.postDelayed(runn3, 2000); 
  14.           tvInfo.post(runn2); 
  15.         } catch (InterruptedException e) { 
  16.           e.printStackTrace(); 
  17.         } 
  18.       } 
  19.     }); 
  20.     t.start(); 
  21.   } 

работает???


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 27 июл 2015, 12:06 

Зарегистрирован: 28 июн 2015, 04:13
Сообщений: 36
Благодарил (а): 17 раз.
Поблагодарили: 1 раз.
Всем доброго дня!
Выходит что НЕЛЬЗЯ вызывать runOnUiThread(runn1); в основном потоке.
Я попробовал убрать создание нового потока и вызвать все наши испытуемые методы из основного потока.
В результате на экране отобразился только runn2 и runn3. Т.е. runOnUiThread(runn1); не сработал.

Код: [ Загрузить ] [ Скрыть ]
  1. try { 
  2.             TimeUnit.SECONDS.sleep(2); 
  3.             runOnUiThread(runn1); 
  4.             TimeUnit.SECONDS.sleep(1); 
  5.             tvInfo.postDelayed(runn3, 2000); 
  6.             tvInfo.post(runn2); 
  7.         } catch (InterruptedException e) { 
  8.             e.printStackTrace(); 
  9.         } 


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 28 июл 2015, 19:05 

Зарегистрирован: 11 июл 2015, 18:54
Сообщений: 7
Благодарил (а): 1 раз.
Поблагодарили: 1 раз.
K_Vladimir Можно, просто ты нагрузил UI-поток, и поэтому экран не обновляется. Экран начнёт обновляться после отработки метода OnCreate (предполагаю, что в нем тестировал код).


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 29 июл 2015, 02:08 

Зарегистрирован: 28 июн 2015, 04:13
Сообщений: 36
Благодарил (а): 17 раз.
Поблагодарили: 1 раз.
rePlay писал(а):
K_Vladimir Можно, просто ты нагрузил UI-поток, и поэтому экран не обновляется. Экран начнёт обновляться после отработки метода OnCreate (предполагаю, что в нем тестировал код).


Попробовал вынести из onCreate. Через кнопку, срабатывают только runn2 и runn3.
Я думаю что вызывать этот метод из основного потока просто нет никакого смысла


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 29 июл 2015, 04:29 

Зарегистрирован: 11 июл 2015, 18:54
Сообщений: 7
Благодарил (а): 1 раз.
Поблагодарили: 1 раз.
K_Vladimir писал(а):
rePlay писал(а):
K_Vladimir Можно, просто ты нагрузил UI-поток, и поэтому экран не обновляется. Экран начнёт обновляться после отработки метода OnCreate (предполагаю, что в нем тестировал код).


Попробовал вынести из onCreate. Через кнопку, срабатывают только runn2 и runn3.
Я думаю что вызывать этот метод из основного потока просто нет никакого смысла

Неправильный вывод. Я же говорю, что ты загрузил UI-поток всякими sleep'ами, из-за чего он не обновляется. Закомментируй
tvInfo.post(runn2); и появится run1. Нужно просто понимать, как отрабатывает твое приложение.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 29 июл 2015, 11:53 

Зарегистрирован: 28 июн 2015, 04:13
Сообщений: 36
Благодарил (а): 17 раз.
Поблагодарили: 1 раз.
rePlay писал(а):
K_Vladimir писал(а):
rePlay писал(а):
K_Vladimir Можно, просто ты нагрузил UI-поток, и поэтому экран не обновляется. Экран начнёт обновляться после отработки метода OnCreate (предполагаю, что в нем тестировал код).


Попробовал вынести из onCreate. Через кнопку, срабатывают только runn2 и runn3.
Я думаю что вызывать этот метод из основного потока просто нет никакого смысла

Неправильный вывод. Я же говорю, что ты загрузил UI-поток всякими sleep'ами, из-за чего он не обновляется. Закомментируй
tvInfo.post(runn2); и появится run1. Нужно просто понимать, как отрабатывает твое приложение.


Вы абсолютно правы. Теперь вижу, что runn1 отрабатывает из основного потока. Да, это важно для понимания всего механизма работы приложения. Спасибо.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 22 авг 2015, 12:45 

Зарегистрирован: 22 авг 2015, 12:31
Сообщений: 1
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
damager82 писал(а):
Первые два похожи и отправляют Runnable на немедленную обработку. Я не знаю в чем их принципиальное отличие. Если у вас есть соображения на этот счет, пишите на форуме в ветке этого урока.

Метод runOnUiThread принадлежит активности, а post принадлежит конкретному виджету.
Собственно, я Runnable-объекты не выносил, а прописывал сразу:

Код: [ Загрузить ] [ Скрыть ]
  1. MainActivity.this.runOnUiThread(new Runnable() 
  2.    @Override 
  3.    public void run() 
  4.    { 
  5.       MainActivity.this.buttonOne.setText("text1"); 
  6.       MainActivity.this.textViewOne.setText("text2"); 
  7.    } 
  8. }); 

Таким образом, можно обращаться к нескольким разным виджетам, чего в post, насколько знаю, делать нельзя.


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 19 ] 

Часовой пояс: UTC + 4 часа


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB