יום שני, דצמבר 20

Threads חלק 2: עם Runnable Messages

זהו פוסט המשך בנושא Threads. בפוסט הקודם,Threads עם Message Handler הובא הסבר רקע, והוזכרו שלוש שיטות למימוש Threads:
Handler עם MessageQueue ו- Data Messages- שיטה זו תוארה בפוסט הנ"ל.
Handler עם MessageQueueu ו- Runnable- זהו נושא הפוסט הנוכחי.
AsyncTask - נושא הפוסט הבא.


מנגנון ה- Runnable
רקע - חזרה על שיטת ה-Data Messages .
בשיטה ה-Message Queue , התקשורת בין ה-Thread שיצרנו לבין ה-Thread הראשי נעשית בעזרת העברת   נתונים  בין ה-Threads.  ה- Handler שולף את הנתונים ומריץ את התוכנית של עצמו. אם ה-Thread רוצה למשל להעביר אינפורמציה ל-UI, הוא ישלח את האינפורמציה כהודעה, וה-Handler יגש ל-UI.

בשיטת ה-runnable ה-Thread שניצור ישלח runnables שהם מודולים להרצה אותם יפעיל ה-Handler  במסגרת ה-Thread הראשי.שליחת ה-runnables ל-MessageQueue נעשית עם פקודות post.



לגבי פקודות ה-post (השייכות ל-)Handler Calss:
קיימות מספר וריאציות של post למשל:

  • (post(runnable r
בדוגמא נשתמש במתודה זו.

  • (postAtTime(runnable r,long upTimeMillis
הביצוע יתקיים בזמן עפ"י הפרמטר השני.

  • (postDelayed(runnable r,long upTimeMillis
הביצוע יתעכב בהתאם לפרמטר השני.
ויש עוד וריאציות של post, ראו Handler Class באתר המפתחים הרשמי.

נעבור לדוגמא:
הדוגמא כמעט זהה לזו מהפוסט הקודם, עם שינויים קלים בלבד - רק מה שהתחייב משינוי השיטה.
לפניכם התוכנית כולה, ולאחריה אגע בהבדלים לעומת התוכנית השניה.
  • החלקים המסומנים באדום - תוספות שקשורות למימוש ה-runnable.
  • החלקים המסומנים בצהוב - קריאות ל-constructor של הThread. עכשיו הן ללא  פרמטר. קודם ה-constructor קיבל את ה-handler.
  • מספר שורות הוסרו: 
    • המימוש של מתודת הhandleMessage בתוך ה-handler
    • בניית ושליחת ההודעה ב-Thread.

מעבר לכך הכל נשאר כמו שהיה.



public class MyThreadHandlerRunnableExample extends Activity {
    EditText editTextThreadOutput;
    EditText editTextThreadOutput2;
    EditText editTextPriority;
    Button buttonThreadOnOff;
    int prioIndx = 1;
    ExampleThread exampleThread1;
    ExampleThread exampleThread2;
    final int THREAD2_PRIORITY = 10;
    final int THREAD1_PRIORITY = 1;
   
     
    /** Called when the activity is first created. */
    @Override public void onCreate(Bundle state) {
        super.onCreate(state);
        setContentView(R.layout.main);
        buttonSetup();
        editTextSetup();
        threadSetup();
    }
     public class ExampleThread extends Thread {
        Handler mHandler = new Handler();
        private final Runnable displayCounter = new Runnable() {
                 public void run() { displayCounterOnUi(counter, threadId); }
             };

        boolean mState = true;
        int counter;
        int threadId;

        void mPrioritySet(int priority){
            setPriority(priority);
        }
        ExampleThread() {
        }
        public void run() {
            counter = 0;
            while (mState) {
                try {
                    Thread.sleep(10);
                }
                catch (InterruptedException e) {
                }
                counter++;
                mHandler.post(displayCounter);
            }
        }
        public void threadStateSet(boolean state) {
            mState = state;
        }
        public boolean threadStateGet(){
            return(mState);
        }
        public void threadIDSet(int val) {
            threadId = val;
        }
        public void threadCounterClear() {
            counter = 0;
        }
    }
     public void displayCounterOnUi(int counter, int threadId){
         if(0 == threadId){
             editTextThreadOutput.setText(Integer.toString(counter));
         }
         else{
             editTextThreadOutput2.setText(Integer.toString(counter));

         }
       
     }

    private void buttonSetup(){
    Button buttonSetPriority = (Button)findViewById(R.id.button_set_priority);
    buttonSetPriority.setText("Thread Priority Set");
    buttonSetPriority.setOnClickListener(
    new Button.OnClickListener() {public void onClick(View v) {
           if (0 == (prioIndx++)%10){
               prioIndx = 1;
           }
           exampleThread1.mPrioritySet(prioIndx);
        editTextPriority.setText("Thrd Priority = " +prioIndx+ "    Thrd 2 Prio= " + THREAD2_PRIORITY);

           exampleThread1.threadCounterClear();
           exampleThread2.threadCounterClear();
          
    } });
    buttonThreadOnOff = (Button)findViewById(R.id.button_thread_onoff);
    buttonThreadOnOff.setText("Thread is On");
    buttonThreadOnOff.setOnClickListener(
    new Button.OnClickListener() {public void onClick(View v) {
        if(exampleThread1.threadStateGet()){
            exampleThread1.threadStateSet(false);
            buttonThreadOnOff.setText("Thread is Off");
        }
        else
        {
            exampleThread1.threadStateSet(true);
            buttonThreadOnOff.setText("Thread is On");
            exampleThread1 = new ExampleThread();
            exampleThread1.start();
        }
        exampleThread1.mPrioritySet(prioIndx);
    } });
    }
    private void  editTextSetup(){
        EditText editText1;
        editTextThreadOutput = (EditText) findViewById(R.id.edit_text2);
        editTextThreadOutput2 = (EditText) findViewById(R.id.edit_text22);
        editText1 = (EditText) findViewById(R.id.edit_text1);
        editTextPriority = (EditText) findViewById(R.id.edit_text3);
    }
    private void threadSetup(){
          exampleThread1 = new ExampleThread();
        exampleThread1.start();
        exampleThread1.mPrioritySet(THREAD1_PRIORITY);
            editTextPriority.setText("Thrd 1 Prio= " +THREAD1_PRIORITY+ "    Thrd 2 Prio= " + THREAD2_PRIORITY);
        exampleThread1.threadIDSet(0);
        exampleThread2 = new ExampleThread();
        exampleThread2.start();
        exampleThread2.mPrioritySet(THREAD2_PRIORITY);
        exampleThread2.threadIDSet(111111);
    }
   
   
}


נתרכז באבני הבניין הדרושים לבניית המנגנון:

אוביקט של ה- ExampleThread. אנחנו כאמור יצרנו שניים כאלה. מסומנים בצהוב.
ה
ההפעלה של ה-Thread -  גם כאן ע"י start:
        exampleThread2.start();
אובייקט ה-runnable:
  private final Runnable displayCounter = new Runnable() {
                 public void run() { displayCounterOnUi(counter, threadId); }
             };

 
displayCounterOnUi   מתודה שתופעל ע"י ה-runnable. היא שייכת ל-class הראשי.  מסומן באדום.

הפעלת ה-runnable:
                mHandler.post(displayCounter);











אין תגובות:

הוסף רשומת תגובה