«

»

Jan 05

Handler

שימוש ב Handler:

 

רקע תאורטי:

 

ה Handler הוא אובייקט שמאפשר לנו לשלוח הודעות לתור ההודעות של תהליכון כלשהו.

אך ראשית בשביל להבין מה זה handler, תור הודעות (ה Message Queue) ו looper נדבר קצת על תבנית העיצוב Pipeline-Thread:

תבנית זאת נועדה לפתור את ההתמודדות של שליחת משימות שצריכות להתבצע בצורה סינכרונית אחת אחרי השנייה.

לדוגמה: העלאת מספר תמונות לשרת / בקשת מידע משרת אחד אחרי השני.

תבנית העיצוב הזאת ממומשת ע”י תור של הודעות (או אפשר לקרוא להם גם משימות) שתהליכונים אחרים מעבירים לתהליכון הזה, (באופן ספציפי Runnable).

התהליכון עובר כל פעם בלולאה על התור, מושך משימה ומבצע אותה. אם אין לו משימות הוא עושה wait וכאשר תכנס משימה לתור היא תעיר אותו ע”י notify.

 

אם כן, מה קשורה תבנית העיצוב Pipeline-Thread ל Handler ול Looper.

 

Looper היא מחלקה שמשתמשים בה בשביל להפוך תהליכון רגיל שיצרנו ל Pipeline-Thread. ז.א. שיהיה לו תור ושהוא ירוץ עליו כל פעם.

 

ה Handler: הוא אובייקט שמאפשר לנו לשלוח הודעות לתור ההודעות של תהליכון כלשהו.

 

משתמשים בו בשביל 2 מטרות:

1. בשביל לקבוע פעולות שהתהליכון יעשה בזמן מאוחר יותר בעתיד.

2. בשביל לקבוע משימות בין תהליכונים שונים.

 

כל Handler משוייך לתהליכון יחיד, התהליכון שנקבע הוא התהליכון שבו התבצעה ההכרזה על ה handler.

 

ה UI-Thread הוא באופן מובנה כבר Pipeline-Thread וכל Handler שתיצור ב onCreate של Activity יהיה משויך אליו.

 
 

דוגמה והסבר:

 

1. בשביל לקבוע פעולות שהתהליכון יעשה בזמן מאוחר יותר בעתיד.

בלחיצת כפתור אנו רוצים שיקרה משהו עוד 5 שניות:

את ה _helloWorldHandler הגדרנו כשדה ב Activity ולכן הוא משויך ל UI-Thread  (גם אם היינו מגדירים ב onCreate של ה Activity הוא עדיין היה משויך ל Ui-Thread).

למעשה מה שאנחנו מגדירים פה הוא שה UI_Thread בעזרת ה Handler שולח לעצמו משימה לביצוע בעוד 5 שניות (לעדכן את ה TextView)

public void onClick(View v) {

	textViewHelloWorld.setText("...");
	int numberOfSeconds = 5;

	_helloWorldHandler.postDelayed(new Runnable() {

		public void run() {

			_helloWorldTextView.setText("Hello World!");

		}		
	}, numberOfSeconds*1000);

}

במתודה זאת אנו משתמשים ב:

postDelayed(new Runnable(), numberOfSeconds*1000);

במצב זה, נכנס לתור של התהליכון runnable חדש שאותו מימשנו והוא יקרה בעוד 5 שניות.

 

2. כאשר אנו רוצים שתהליכון אחר ישלח הודעה, נעביר לו את ה handler שלנו והוא יצור Message שאותו הוא יעביר ל handler לשליחה בעזרת sendMessage.

דוגמא לשימוש ב handler שמעבירים לתהליכון ו counter. תהליכון ידווח לשה handler כל שניה למשך counter שניות.

 

0. הגדרות:

CountHandler _countHandler = new CountHandler();
CounterRunnable _counterRunnable = new CounterRunnable(10, _countHandler);
Thread 	_counterThread = new Thread(_counterRunnable, "Counter Thread");

 

1. נגדיר handler שכאשר הוא מקבל תשובה הוא משנה את ה text בשדה:

    private class CountHandler extends Handler {

		public void handleMessage(Message msg) {

			Integer secondToDisplay = (Integer) msg.obj;
			_tenSecondsTextView.setText(String.valueOf(secondToDisplay));

		}

    }

 

2. כעת נגדיר את ה Runnable שהתהליכון יריץ:

    private class CounterRunnable implements Runnable {

		private int _count = 0;
		private CountHandler _handler;

		public CounterRunnable(int count, CountHandler handler) {

			_count = count;
			_handler = handler;

		}

 

כל שניה התהליכון ידווח ל handler עם ה sendMessage את הזמן שעבר

		@Override
		public void run() {

			while(_count >= 0 && !Thread.currentThread().interrupted()){

				Message secondToDisplay = Message.obtain();
				secondToDisplay.obj = new Integer(_count);
				_handler.sendMessage(secondToDisplay);
				_count--;
				try {

					Thread.currentThread();
					Thread.sleep(1000);

				} catch (InterruptedException e) {

					Log.d("Text", "Lior: Thread interrupted");
					Thread.currentThread().interrupt();

				}

			}

		}

		protected void setCounter(int count) {

			_count = count;

		}

    }

 

3. ולסיום, בלחיצת כפתור נאפס את ה counter ל 10 וניצור תהליכון חדש, אם לא קיים כבר תהליכון שמריץ את ה runnable (לדוגמא כאשר לוחצים פעמיים על הכפתור תוך פחות מ 10 שניות). ונריץ אותו.

		tenSecondsButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {

				_counterRunnable.setCounter(10);

אם התהליכון כבר מריץ אותו לא נעשר כלום, כי שינינו כבר את ה count של ה runnable של התהליכון .

				if(_counterThread.isAlive()) {

						//Do nothing

				} else {

אם אין תהליכון שמריץ את ה runnable, ניצור חדש ונריץ אותו

					_counterThread = new Thread(_counterRunnable, "Counter Thread");
					_counterThread.start();	

				}

			}

        });

 
 

לינק להורדת הפרויקט לדוגמה

 

בהצלחה !

 

Leave a Reply

Your email address will not be published.

אתם יכולים להשתמש באפשרויות ותגי ה-HTMLהבאים: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>