Обновление View в другом потоке

Ответить
Lighter
Сообщения: 61
Зарегистрирован: 13 авг 2013, 16:39

Обновление View в другом потоке

Сообщение Lighter » 14 июл 2014, 16:41

Всем привет!

Когда я обновляю View в другом потоке (через View.post(Runnable)), переданное сообщение может не прийти, например, как в следующем коде:

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

public class MainActivity extends Activity {	
	private TextView output;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		output = new TextView(this);
		setContentView(output);
        
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					appendText("A");
					Thread.sleep(100);
					appendText("B");					
				} catch (Exception e) {
					appendText(e.toString());
				}				
			}			
		}).start();	   
	}
	
	private void appendText(final Object msg) {
		output.post(new Runnable() {
			@Override
			public void run() {
				output.setText(output.getText() + "\n" + msg);				
			}			
		});
	}
}
Если убрать

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

Thread.sleep(100);
, то не напечатается вообще ничего, если поставить

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

Thread.sleep(100);
перед

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

appendText("A");
, то печатаются оба сообщения.

Почему так происходит?

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Обновление View в другом потоке

Сообщение altwin » 15 июл 2014, 14:34

если вы руками создаете thread то и о синхронизации потоков думать только вам. Чем вам не подошел стандартный AsyncTask ?
Изображение

Lighter
Сообщения: 61
Зарегистрирован: 13 авг 2013, 16:39

Re: Обновление View в другом потоке

Сообщение Lighter » 16 июл 2014, 14:04

altwin, здесь вопрос не в синхронизации или использовании AsyncTask. Просто заметил такое поведение и стало интересно, почему так происходит.

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Обновление View в другом потоке

Сообщение altwin » 16 июл 2014, 14:11

Lighter писал(а):altwin, здесь вопрос не в синхронизации или использовании AsyncTask. Просто заметил такое поведение и стало интересно, почему так происходит.
Здесь вопрос именно в синхронизации потоков. sleep - это очень дурной тон и доказанно это было идиотами делающими eclipse, которые в lancher добавили sleep и в итоге он висел несколько секунд в не зависимости от событий, к слову этих людей уже уволили. Порядок выполнения потока не гаррантирован и получите вы сообщение или нет зависит только от счастливой случайности в данном случае, методом sleep вы просто даете больше времени на получение результата, но когда потоков будет больше или больше времени потребуется на получение сообщения вы что будете sleep на больший интервал выставлять??? AsyncTask уже написан за вас и вы можете выполнять код непосредственно в методе onProgressUpdate, в котором заметьте никаких sleep нет. То, что у вас этот код дает похожий с ожидаемым результат - случайность и причина только в том, что приложение очень маленькое, по сути -это не рабочий код. И именно для этого придумали тесты... А по поводу работы с потоками -это не такая простая тема, почитайте для начала - http://www.amazon.com/Java-Concurrency- ... 0321349601 Есть довольно не плохой мини курс по основам - https://www.youtube.com/watch?v=s032s29 ... -qJdf38oKp
Изображение

Lighter
Сообщения: 61
Зарегистрирован: 13 авг 2013, 16:39

Re: Обновление View в другом потоке

Сообщение Lighter » 17 июл 2014, 11:00

Это всё понятно, но всё же вопрос в другом: почему пропадает один вывод сообщения? Текст должен добавиться 2 раза, но добавляется только тот текст, который после Sleep.

Другой, очень похожий пример:

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

new Thread(new Runnable() { 
           @Override 
           public void run() { 
               try { 
                   appendText("A");
                   appendText("B");                     
               } catch (Exception e) { 
                   appendText(e.toString()); 
               }                 
           }             
       }).start();
Здесь нет Sleep, и текст не выводится вообще.
И вопрос в том, почему? TextView не успевает до конца инициализироваться?

Ответить