Урок 80. Handler. Немного теории. Наглядный пример использования

Обсуждение уроков
Аватара пользователя
elron
Сообщения: 31
Зарегистрирован: 14 окт 2012, 13:29

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение elron » 15 окт 2014, 15:27

Если например хендлер создать в новом потоке поток2 и передать ему сообщение из потока3, то хендлер будет выполнять команды из потока2 ?!

Bulvasaur
Сообщения: 6
Зарегистрирован: 02 июл 2015, 14:18

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение Bulvasaur » 06 июл 2015, 12:28

Добрый день!
Немного не понятно почему зависает приложение, когда начинает "закачивать" файлы? Вот оно заходит в цикл
for (int i = 1; i <= 10; i++)
потом одну секунду выполняет метод
// долгий процесс
downloadFile();
но потом-то должно выполнится это
// обновляем TextView
tvInfo.setText("Закачано файлов: " + i);
А оно не выполняется, а только пишется в лог. Почему основной процесс остается занятым, если он уже однократно выполнил downloadFile();
То есть, насколько я понимаю, только в течение одной секунды основной поток занят, а потом возникает возможность прорисовать экран, но этого не происходит, потому что поток чем-то занят. Так чем он получается занят?
Растолкуйте, пожалуйста.

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение doter.ua » 06 июл 2015, 15:48

Bulvasaur писал(а):Добрый день!
Немного не понятно почему зависает приложение, когда начинает "закачивать" файлы? Вот оно заходит в цикл
for (int i = 1; i <= 10; i++)
потом одну секунду выполняет метод
// долгий процесс
downloadFile();
но потом-то должно выполнится это
// обновляем TextView
tvInfo.setText("Закачано файлов: " + i);
А оно не выполняется, а только пишется в лог. Почему основной процесс остается занятым, если он уже однократно выполнил downloadFile();
То есть, насколько я понимаю, только в течение одной секунды основной поток занят, а потом возникает возможность прорисовать экран, но этого не происходит, потому что поток чем-то занят. Так чем он получается занят?
Растолкуйте, пожалуйста.
Какая еще возможность? это все один мейн поток, код выполняется последовательно. Параллельность возникает между разными потоками.
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

Bulvasaur
Сообщения: 6
Зарегистрирован: 02 июл 2015, 14:18

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение Bulvasaur » 06 июл 2015, 16:08

doter.ua писал(а):Какая еще возможность? это все один мейн поток, код выполняется последовательно. Параллельность возникает между разными потоками.
Понятно, что код выполняется последовательно. Это и не понятно)
1-й шаг цикла: выполнился downloadFile();
Следующий шаг цикла: можно выполнить tvInfo.setText("Закачано файлов: " + i); - этого не происходит. Почему? Чем конкретно занят основной поток?
Если он занят циклом

for (int i = 1; i <= 10; i++) {
// долгий процесс
downloadFile();
// обновляем TextView
tvInfo.setText("Закачано файлов: " + i);
// пишем лог
Log.d(LOG_TAG, "Закачано файлов: " + i);
}

то что ему мешает обновить вью о количестве закачанных файлов?
Или тут получается, типа: "Я занят закачкой файлов и не могу разорваться".
То есть основной поток выполняет downloadFile(); потом пропускает tvInfo.setText(); потому что занят и не может снизойти до вывода на экран, а затем выводит сообщение в лог, на которое у него ресурсы есть. То есть основной поток может производить любые расчеты, но не может их совмещать с выводом чего-либо на экран? Правильно я понимаю?

То есть если я напишу что-то подобное:

int j=0;
for (int i=0; i<10; i++) {
j=i+5;
tvInfo.setText(j);
Log.d(LOG_TAG, "j= "+j);
Tread.sleep(1000);
}

то приложение зависнет на 10 секунд, выведутся только сообщения в лог, а вью так ни разу и не обновится?
То есть один отдельно взятый поток может либо что-то рассчитывать, либо что-то делать с экраном? А согласует их действия хэндлер?

Я, вероятно, какой-то совсем тупой вопрос задаю, но иначе мне не разобраться. Извините.
Последний раз редактировалось Bulvasaur 06 июл 2015, 16:26, всего редактировалось 1 раз.

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение doter.ua » 06 июл 2015, 17:36

[quote="Bulvasaur"][/quote]

Не вырывай код из контекста, в уроке кроме цикла есть еще
Thread t = new Thread(new Runnable() {
public void run() {
это как раз отдельный поток, который не сможет менять вью т.к. они остались в другом потоке. А вот хендлер может это делать с помощью msg.

ЗЫ в уроке специально показали плохой пример, дальше будет решение.
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

Bulvasaur
Сообщения: 6
Зарегистрирован: 02 июл 2015, 14:18

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение Bulvasaur » 07 июл 2015, 14:27

Ok. Задам вполне конкретный вопрос. Почему это tvInfo.setText("Закачано файлов: " + i); не может быть выполнено после этого downloadFile();? Ведь в данный конкретный момент перехода от одной строчки кода к следующей поток не занят. Или занят? Чем?

Аватара пользователя
klblk
Сообщения: 1097
Зарегистрирован: 18 окт 2012, 11:17
Откуда: г. Красноярск

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение klblk » 07 июл 2015, 15:41

Bulvasaur писал(а):Ok. Задам вполне конкретный вопрос. Почему это tvInfo.setText("Закачано файлов: " + i); не может быть выполнено после этого downloadFile();? Ведь в данный конкретный момент перехода от одной строчки кода к следующей поток не занят. Или занят? Чем?
Нужно глубоко покопаться в исходниках, чтобы понять всю суть. Но думаю просто View прорисовывается не сразу в ходе выполнения метода onClick() (ну и любого другого метода из ui потока), т.к. во время метода вы можете поменять кучу разных view, и при каждом таком изменении "рисовать" будет накладно.
Примерно так: Отработал метод onClick(), система проверила нужно или нет обновлять view, и если нужно обновляет.

Bulvasaur
Сообщения: 6
Зарегистрирован: 02 июл 2015, 14:18

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение Bulvasaur » 07 июл 2015, 16:27

klblk писал(а):Нужно глубоко покопаться в исходниках, чтобы понять всю суть. Но думаю просто View прорисовывается не сразу в ходе выполнения метода onClick() (ну и любого другого метода из ui потока), т.к. во время метода вы можете поменять кучу разных view, и при каждом таком изменении "рисовать" будет накладно.
Примерно так: Отработал метод onClick(), система проверила нужно или нет обновлять view, и если нужно обновляет.
Спасибо. Что-то зашевелилось в голове. Не спроста этот хэндлер, в общем.

burnix
Сообщения: 4
Зарегистрирован: 21 май 2015, 14:53

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение burnix » 08 июл 2015, 20:40

в АS может возникнуть проблема при автоматическом импорте Handler. Метод sendEmptyMessage() может быть "cannot resolved", то есть покраснеть как целомудренная девушка при виде порно. Проблема решается ручной заменой импорта java.util.logging.Handler на android.os.Handler.

0800009
Сообщения: 36
Зарегистрирован: 08 мар 2014, 20:40

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение 0800009 » 30 янв 2016, 13:15

Мне немного помог понять потоки и хендлер такой пример,
а именно то что вызывая один и тот же метод runLongProcess
из разных потоков мы получаем различные результаты.

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

public class MainActivity extends Activity {

	 private Button clickBtn;
	 private Button clickBtn2;
	    private ProgressDialog progressDialog;
	 
	    private Handler handler = new Handler() {
	 
	        @Override
	        public void handleMessage(Message msg) {
	            super.handleMessage(msg);
	            progressDialog.dismiss();
	           
	        }
	    };
	@Override
	protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        LinearLayout ll = new LinearLayout(this);
        ll.setOrientation(LinearLayout.VERTICAL);
 
        clickBtn = new Button(this);
        clickBtn2=new Button(this);
        ll.addView(clickBtn);
        ll.addView(clickBtn2);
        
        clickBtn.setText("Click me");
        
        clickBtn.setOnClickListener(new OnClickListener() {
 
            @Override
            public void onClick(View v) {
                processThread();
            }
        });
 
        setContentView(ll);
       
    
	 clickBtn2.setOnClickListener(new OnClickListener() {
		 
         @Override
         public void onClick(View v) {
       runLongProcess();
         }
     });

    
 }
	 private void processThread() {
	        progressDialog = ProgressDialog.show(MainActivity.this, "Wait", "Running loooong process...");
	 
	        new Thread() {
	            public void run() {
	                runLongProcess();
	                handler.sendEmptyMessage(2);
	               
	            }
	        }.start();
	    }
	 private void runLongProcess() {
		 
	     try {
	            Thread.sleep(5*1000);
	            Log.e("MainActivity", "LongProcess");
	            clickBtn2.setText("Click me");
	        } catch (InterruptedException e) {
	            Log.e("MainActivity", e.getMessage());
	        }
	    }


WKBAPKA
Сообщения: 32
Зарегистрирован: 03 янв 2014, 14:28

Re: Урок 80. Handler. Немного теории. Наглядный пример испо

Сообщение WKBAPKA » 06 фев 2016, 13:30

В Android Studio не получается получить ошибку. нажимаю на старт, на секунду замирает и дальше себе крутиться. но в логи ничего не выводит.
это особенность эмулятора?

и еще вопрос. При создании нового потока, при создании объекта Runnable() студио автоматически подставил метод Run() с ключевым словом @overide
убрал, ничего не поменялось в выполнении метода. Насколько я понимаю, это означает, что мы переопределяем метод... запутался совсем...

ПЫ СЫ: проверил на телефоне. тоже самое, ошибку не выдает

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

package consulting.brick.wkbapka.p0801_handler;

import android.app.Activity;
import android.util.Log;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;
import android.view.View;


import java.util.concurrent.TimeUnit;

public class MainActivity extends Activity {
    final String LOG_TAG = "myLog";
    Handler h;
    TextView tvInfo;
    Button btnStart;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvInfo = (TextView) findViewById(R.id.tvInfo);

    }

    public void onСlick(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();
                            tvInfo.setText("Закачано файлов " + i);
                            Log.d(LOG_TAG, "Закачано файлов " + i);
                        }
                    }
                });

                break;

            case R.id.btnTest:
                Log.d(LOG_TAG,"test");
                break;
            default:
                break;
        }

    }

    void downloadFile() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();

        }


    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

все, вопрос снят, забыл запустить поток


levgilman
Сообщения: 2
Зарегистрирован: 11 сен 2018, 08:48

Сообщение levgilman » 27 ноя 2018, 11:54

Вариант с тредом, где должно выбивать, у меня нормально работает, пишет на экране.

alaya
Сообщения: 2
Зарегистрирован: 19 дек 2019, 14:53

Re: Урок 80. Handler. Немного теории. Наглядный пример использования

Сообщение alaya » 19 дек 2019, 14:55

Видимо в последних версиях что-то изменилось, работает как и с Thread, так и с Handler.

Ответить