Урок 84. Handler. Обработка Runnable

Обсуждение уроков
Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Урок 84. Handler. Обработка Runnable

Сообщение damager82 » 03 июн 2012, 23:00

В этом уроке:
- работаем с Handler и Runnable


Click here to read this article!
Последний раз редактировалось damager82 20 май 2017, 20:09, всего редактировалось 4 раза.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 84. Handler. Обработка Runnable

Сообщение Foenix » 23 окт 2012, 19:08

Тут почему-то еще не писали, буду первой :)
Объясните, пожалуйста, если я выбрала прогрессбар кружком вида @android:style/Widget.ProgressBar.Large
Как мне его разместить в Layout-ах так, чтоб он был поверх всех элементов вьюшки? т.е. допустим нажали на кнопочку, пошло действие в бэкграунде, все элементы вьюшки затенились и на экране это колечко крутится.
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Урок 84. Handler. Обработка Runnable

Сообщение AndreyI » 23 окт 2012, 19:35

Для этого нужно использовать ProgressDialog

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 84. Handler. Обработка Runnable

Сообщение Foenix » 23 окт 2012, 21:21

Спасибочки!
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Blackbern
Сообщения: 2
Зарегистрирован: 18 дек 2012, 23:31

Re: Урок 84. Handler. Обработка Runnable

Сообщение Blackbern » 18 дек 2012, 23:40

В новом (не главном UI потоке) вызываем h.post(updateProgress); где обращаемся к элементу интерфейсу Count.setProgress(cnt);
По идее это небезопасно. Или тот Runnable который мы отдали хендлеру имеет безопасный доступ к UI????
И не плохо было б добавить условие в showinfo а то хендлер продолжает сам себя вызывать:
if (cnt >= max) h.removeCallbacks(showInfo);

behzodbek
Сообщения: 58
Зарегистрирован: 23 дек 2012, 22:58
Откуда: UZB Namangan

Re: Урок 84. Handler. Обработка Runnable

Сообщение behzodbek » 24 дек 2012, 08:44

Вопрос знатокам в Уроке 80 сказали
  • При попытке выполнить этот код (не в основном потоке) мы получили ошибку «Only the original thread that created
    a view hierarchy can touch its views». Если по-русски, то «Только оригинальный поток, создавший view-
    компоненты, может взаимодействовать с ними». Т.е. работа с view-компонентами доступна только из основного
    потока. А новые потоки, которые мы создаем, не имеют доступа к элементам экрана

а на уроке 84 изменили Активити с другого потока. А я думал тока с основного потока можно изменить Активити.

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

    Thread t = new Thread(new Runnable() {
      public void run() {
        try {
          for (cnt = 1; cnt < max; cnt++) {
            TimeUnit.MILLISECONDS.sleep(100);
            // обновляем ProgressBar
            h.post(updateProgress);
          }
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    });
    t.start();
  }
  // обновление ProgressBar
  Runnable updateProgress = new Runnable() {
    public void run() {
      pbCount.setProgress(cnt);
    }
  };
  // показ информации
  Runnable showInfo = new Runnable() {
    public void run() {
      Log.d(LOG_TAG, "showInfo");
      tvInfo.setText("Count = " + cnt);
      // планирует сам себя через 1000 мсек
      h.postDelayed(showInfo, 1000);
    }
  };
Я чтот не понимаю

Аватара пользователя
KamiSempai
Сообщения: 1339
Зарегистрирован: 17 фев 2012, 21:23
Откуда: Мордор

Re: Урок 84. Handler. Обработка Runnable

Сообщение KamiSempai » 24 дек 2012, 11:43

behzodbek писал(а):а на уроке 84 изменили Активити с другого потока. А я думал тока с основного потока можно изменить Активити.
В этом уроке код выполняется не через прямой вызов, а через обработку сообщений. Handler h был создан в основном потоке, а значит все сообщения отправленные через него будут выполнены в основном потоке.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

alexshr
Сообщения: 6
Зарегистрирован: 24 окт 2012, 18:10

Re: Урок 84. Handler. Обработка Runnable

Сообщение alexshr » 21 янв 2013, 22:39

behzodbek писал(а):а на уроке 84 изменили Активити с другого потока. А я думал тока с основного потока можно изменить Активити.
Тут путаница получается в понимании:
Как мы учили в java, в интерфейсе Runnable методом run() выделяется код, запускаемый в отдельном потоке. И когда мы видим такое:

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

Runnable updateProgress = new Runnable() {
    public void run() {
      pbCount.setProgress(cnt);
    }
  };
или такое:

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

Runnable showInfo = new Runnable() {
    public void run() {
      Log.d(LOG_TAG, "showInfo");
      tvInfo.setText("Count = " + cnt);
      // планирует сам себя через 1000 мсек
      h.postDelayed(showInfo, 1000);
    }
  };
то сразу начинает мерещиться старт нового потока. Но для этого нужен вызов start(), а в вышеприведенном коде, который и работает с view, этого нет, а есть просто метод с названием run(), который и запускается внутри основного потока

Snakebyte
Сообщения: 20
Зарегистрирован: 20 дек 2012, 08:18

Re: Урок 84. Handler. Обработка Runnable

Сообщение Snakebyte » 02 фев 2013, 21:51

Подскажите, почему в setAlpha alpha не меняется?

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

public class ImageFragment extends Fragment {
	
	Quiz quiz;
	Handler h;
	Thread t;
	ScaledImageView v;
	int alpha;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
				
		LinearLayout view = (LinearLayout) inflater.inflate(R.layout.quizimage, null);
		v = (ScaledImageView) view.findViewById(R.id.image);
		v.setBackgroundDrawable(quiz.quizData.background);
		v.setImageDrawable(quiz.quizData.image);
		v.setAlpha(quiz.quizData.isComplete ? 254 : 0);
		
		return view;
	}

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
		
		quiz = (Quiz) activity;
	}
	
	public void fadeOut(ScaledImageView v) {

		h = new Handler();

		t = new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					for (int alpha = 0; alpha < 255; alpha++) {
						TimeUnit.MILLISECONDS.sleep(10);
						h.post(setAlpha);						
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});

		t.start();		
	}

	Runnable setAlpha = new Runnable() {
		
		@Override
		public void run() {
			Log.d("mylog", "Alpha = " + alpha);
			v.setAlpha(alpha);			
		}
	};
}
fadeOut() вызывается из Activity

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

imageFragment.fadeOut((ScaledImageView) imageFragment.getView().findViewById(R.id.image));

Snakebyte
Сообщения: 20
Зарегистрирован: 20 дек 2012, 08:18

Re: Урок 84. Handler. Обработка Runnable

Сообщение Snakebyte » 03 фев 2013, 12:44

Заменил на AsyncTask, все работает.

evgenius_b
Сообщения: 10
Зарегистрирован: 23 авг 2013, 13:26

Re: Урок 84. Handler. Обработка Runnable

Сообщение evgenius_b » 30 авг 2013, 08:58

Гуру, а как остановить это Runnable?
Я дошел до урока 87 (закодил и отправил на виртуальный девайс приложения) и случайно увидел, что в логах LogCat с периодом в 1с появляются сообщения от кода этого урока. Я так понимаю, нужно принудительно завершить работу после выполнения например 100 циклов.

SevenXP
Сообщения: 113
Зарегистрирован: 21 июл 2013, 18:20

Re: Урок 84. Handler. Обработка Runnable

Сообщение SevenXP » 05 сен 2013, 11:23

У меня есть 2 проблемы

1)Планшет вызывает 2 раза метод OnCreate 1 раз когда создает активити потом он понимает что ему нужно его перевернуть (
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.find_a_star_activity); ...
)

У моего планшета по умолчанию отображение рабочего стола, если отключить авто поворот, ландшафт

2) Вытекает из 1-вой не могу понять, как проверить, если процесс запущен не запускать опять. Этот код в OnCreate;

Create_Thread = new Thread(new Runnable() {

@Override
public void run() {
// TODO Auto-generated method stub
Get_Info_Cursor_Honorees_FirstName();
Handler_FAS.sendEmptyMessage(VIEW_LIST);
}
});

if (Create_Thread.getState() != Thread.State.RUNNABLE && Create_Thread.isAlive() == false) {
Create_Thread.start();
}

TomPO
Сообщения: 6
Зарегистрирован: 24 авг 2013, 00:06

Re: Урок 84. Handler. Обработка Runnable

Сообщение TomPO » 15 сен 2013, 12:08

Если, если, например, мы создали поток.

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

Thread t = new Thread(new Runnable() {
      public void run() {
        try {
          for (cnt = 1; cnt < max; cnt++) {
            TimeUnit.MILLISECONDS.sleep(100);
            // обновляем ProgressBar
            h.post(updateProgress);
          }
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    });
    t.start();
Этот поток отправляет сообщение в основной поток. Метод updateProgress будет выполняться в основном потоке, или в созданном потоке t?

sensetiw
Сообщения: 1
Зарегистрирован: 17 сен 2013, 12:37

Re: Урок 84. Handler. Обработка Runnable

Сообщение sensetiw » 18 сен 2013, 08:10

Как останавливать поток и запускать заново?

EvilAngel
Сообщения: 28
Зарегистрирован: 16 апр 2013, 23:55

Re: Урок 84. Handler. Обработка Runnable

Сообщение EvilAngel » 02 ноя 2013, 01:35

Добрый день!
Столкнулся с такой проблемой. Нужно при работе с WallpaperService на основе Canvas (не OpenGL) организовать Fade-эффект между двумя изображениями. И всё бы хорошо, если не были бы возможны ситуации как двойного или одинарного тапа, так и свайпа в разных направлениях во время данного эффекта. По Fade-эффекту достаточно много примеров в Интернете как на stackoverflow.com, так и в независимых источниках, но все они касаются анимации вьюшек, а никак не моего случая. Как я понимаю с вьюхами всё гараздо проще (есть реализуемый метод onDraw() и вызываемый метод invalidate()). На случай обоевой канвы в нашем распоряжении два холдеровых метода (locCanvas() и unlockCanvasAndPost()).
Чтобы сильно много не болтать, скажу суть. Для реагирования на тапы во время перехода(ни до, ни после) всю логику этого самого перехода я хотел выделить в отдельный поток, а захват и сброс канвы на экран реализовать в обработчике сообщений handleMessage(). Но при таком раскладе никакого эффекта не происходит (только мерцание изображений без плавного транспорирования).

Подскажите, пожалуйста, может кто сталкивался с такой проблемой, как здесь можно реализовать задуманное?

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

public class MyClass extends WallpaperService {

          //Вспомогательный класс для передачи в хэндлер канвы и холдера
          class MyObject{
                    private Canvas canvas = null;
                    private SurfaceHolder holder = null;

                    MyObject(SurfaceHolder sh, Canvas cv){
                              canvas = cv;
                              holder= sh;
                    }
          
                    public SurfaceHolder getHolder(){return holder;}
                    public Canvas getCanvas(){return canvas;}
          }

          //Хэндлер, посылающий и обрабатывающий сообщения
          private final Handler mHandler = new Handler(){
                    public void handleMessage(android.os.Message msg)   {
                              MyObject myObject= (MyObject)msg.obj;
                                        switch(msg.what){
                                                  case 1:
                                                            Canvas c = myObject.getCanvas();
                                                            c = myObject.getHolder().lockCanvas();
                                                            break;
                                                  case 2:
                                                            myObject.getHolder().unlockCanvasAndPost(myObject.getCanvas());
                                                            break;
                                        }
                    }
          };
          
          //Класс рендеринга
          class WallpaperEngine extends Engine implements OnSharedPreferenceChangeListener {
                    .........................
                    private final Paint mPaint = new Paint();
                    private boolean mVisible = false;
                    private Bitmap mBitmap = null;
                    private Bitmap mPreviousBitmap = null;
                    private long mLastDrawTime = 0;
                    private final GestureDetector doubleTapDetector;
                    .........................

                    private final Runnable mWorker = new Runnable() {
                              public void run() {
                                        if (mDuration > 0)
                                        drawFrame();
                              }
                    };

                    WallpaperEngine() {
                              .......................
                              doubleTapDetector = new GestureDetector(HDLiveWallpaper.this,
                                        new SimpleOnGestureListener() {
                                                  @Override
                                                  public boolean onDoubleTap(MotionEvent e) {
                                                            if (mTouchEvents) {
                                                                      mLastDrawTime = 0;
                                                                      if(myThread!=null)stopThread(myThread);
                                                                      drawFrame();
                                                                      return true;
                                                            }
                                                            return false;
                                                  }
                                        }
                              );
                    }

                    private void stopThread(MyThread thread)
                    {
                              if( myThread != null )  myThread = null;
                    }
                    .................
                    .................
                    .................
                    //Метод отрисовки (привожу только более менее относящееся к вопросу)
                    void drawFrame() {
                              final SurfaceHolder holder = getSurfaceHolder();
                              Canvas c = null;
                              //Получаем первое или следующее изображение для отрисовки
                              ...................
                              //В случае первого входа в функцию или различных манипуляция до и после эффекта
                              //фиксируем канву:
                              c = holder.lockCanvas();
                              ...................
                              c.drawColor(Color.BLACK);
                              c.drawBitmap(mBitmap, xPos, yPos, mPaint);
                              ...................
                              if (c != null){
                                        if((mPreviousBitmap==null) || (mPreviousBitmap==mBitmap))
                                                  holder.unlockCanvasAndPost(c);
                                        else{						
                                                  if(mTransition==1){
                                                            myThread = new MyThread(holder,c);
                                                            myThread.start();
                                                  }
                                                  else
                                                            holder.unlockCanvasAndPost(c);
                                        }
                                        mPreviousBitmap = mBitmap;
                              }
                              ....................
                              mHandler.removeCallbacks(mWorker);
                              if (mVisible/*-если мы в фореграунде*/) {
                                        mHandler.postDelayed(mWorker, 1000 / 2); //mWorker - это Runnable, который запускает поначалу и далее выполняет метод
                                                                                                         //drawFrame() циклически или по требованию
                              }
                    }

                    //Поток с Fade-эффектом
                    public class MyThread extends Thread{
                              private SurfaceHolder _surfaceHolder;
                              private Canvas c;
          
                              public MyThread(SurfaceHolder holder, Canvas canvas){
                                        _surfaceHolder = holder;
                                        c = canvas;
                              }
			
                              public SurfaceHolder getHolder()  { return  _surfaceHolder; }
                              public Canvas getCanvas()  { return c; }

                              public void run(){
                                        c.drawBitmap(mBitmap, 0, 0, mPaint);
                                        int tmpPaintAlpha = mPaint.getAlpha();
                                        mPaint.setAlpha(254);
                                        c.drawBitmap(mPreviousBitmap, 0, 0, mPaint);

                                        //Первым делом необходимо разрочить ранее(в drawFrame()) залоченную канву
                                        MyObject myObject = new MyObject(_surfaceHolder,c);
                                        Message msg = mHandler.obtainMessage(2, myObject);
                                        mHandler.sendMessage(msg);          //_surfaceHolder.unlockCanvasAndPost(c);
                                        mPaint.setAlpha(tmpPaintAlpha);
                    
                                        int i=253;
                                        while(i!=0){
                                                  msg = mHandler.obtainMessage(1, myObject);
                                                  mHandler.sendMessage(msg);//c = _surfaceHolder.lockCanvas();
                              
                                                  c.drawBitmap(mBitmap, 0, 0, mPaint);
                                                  mPaint.setAlpha(i);
                                                  c.drawBitmap(mPreviousBitmap, 0, 0, mPaint);
                              
                                                  msg = mHandler.obtainMessage(2, myObject);
                                                  mHandler.sendMessage(msg);//_surfaceHolder.unlockCanvasAndPost(c);

                                                  mPaint.setAlpha(255);
                                                  i-=1;
                                        }
                                        myThread = null;
                              }
                    }
          }
}
Простите великодушно за многобуквенность!
Заранее благодарен любым ответам!
Последний раз редактировалось EvilAngel 02 ноя 2013, 10:19, всего редактировалось 3 раза.

EvilAngel
Сообщения: 28
Зарегистрирован: 16 апр 2013, 23:55

Re: Урок 84. Handler. Обработка Runnable

Сообщение EvilAngel » 02 ноя 2013, 01:43

sensetiw писал(а):Как останавливать поток и запускать заново?
Остановить можно простым [syntax=java5]mThread = null[/syntax], приостановить [syntax=java5]mThread.interrupt()[/syntax], а запуск обычным [syntax=java5]mThread.start()[/syntax].

Sebler
Сообщения: 30
Зарегистрирован: 17 апр 2014, 17:50

Re: Урок 84. Handler. Обработка Runnable

Сообщение Sebler » 04 окт 2014, 17:31

alexshr писал(а): то сразу начинает мерещиться старт нового потока. Но для этого нужен вызов start(), а в вышеприведенном коде, который и работает с view, этого нет, а есть просто метод с названием run(), который и запускается внутри основного потока
Думаю он всё-таки не запускается внутри основного потока, а запускается внутри потока "message queue", который и обрабатывает всё, что приходит в хендлер.

K_Vladimir
Сообщения: 36
Зарегистрирован: 28 июн 2015, 03:13

Re: Урок 84. Handler. Обработка Runnable

Сообщение K_Vladimir » 26 июл 2015, 23:20

Доброго всем дня!
Подскажите, Бывают ли случаи когда сообщение отправляется из основного потока в новые потоки? А-то в уроках все время отправляли только в основной.

KupueIIIKo
Сообщения: 3
Зарегистрирован: 25 июл 2015, 09:27

Re: Урок 84. Handler. Обработка Runnable

Сообщение KupueIIIKo » 30 июл 2015, 10:21

Изменения не какие не происходили? я уже какой раз пытаюсь сделать Android Studio выдает всякую шляпу...
Вообщем все перепробывал с фрагмента запускаю код, выполняется разок в начале и все...
Может я чето не так делаю... Но в итоге мне надо у webview.loadurl сделать

Eduard
Сообщения: 1
Зарегистрирован: 20 авг 2015, 09:45

Re: Урок 84. Handler. Обработка Runnable

Сообщение Eduard » 20 авг 2015, 09:49

где в коде указано,что счетчик увеличивается каждый раз на 10?Не совсем понял как это

Ответить