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

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

Добавлено: 14 июл 2014, 16:41
Lighter
Всем привет!

Когда я обновляю 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");
, то печатаются оба сообщения.

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

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

Добавлено: 15 июл 2014, 14:34
altwin
если вы руками создаете thread то и о синхронизации потоков думать только вам. Чем вам не подошел стандартный AsyncTask ?

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

Добавлено: 16 июл 2014, 14:04
Lighter
altwin, здесь вопрос не в синхронизации или использовании AsyncTask. Просто заметил такое поведение и стало интересно, почему так происходит.

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

Добавлено: 16 июл 2014, 14:11
altwin
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

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

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

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

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

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