
AsyncTask מריץ קוד בתרד נפרד ומאפשר גם לעדכן את ה-UI במקומות הנכונים, ולכן הוא פותר את שתי הבעיות שנוצרו עם thread רגיל. ההרצאה הופכת את PrimesFinder ל-AsyncTask.Runnable: PrimesFinder יורש מ-AsyncTask, מחלקה Generic עם שלושה טיפוסים. הראשון הוא מה שהיא מקבלת, כאן Long (תחילת הטווח וסופו). השני הוא מה שהיא מדווחת תוך כדי עבודה, כאן Void כי עדיין לא מדווחים. השלישי הוא התוצאה הסופית, כאן String עם כל הראשוניים.doInBackground: פונקציה חובה, שרצה בתרד נפרד ולכן אסור לה לגעת ב-UI. מקבלת פרמטרים בצורת Long..., כלומר מערך: params[0] הוא start ו-params[1] הוא end. כאן נמצא האלגוריתם הארוך, והיא מחזירה את stringBuilder.toString().onPostExecute: רצה אוטומטית בתרד ה-UI בסיום, ומקבלת את הערך ש-doInBackground החזירה. לכן מותר בה לגעת ב-UI, והיא קוראת ל-listener.onSuccess(result). מקובל לקרוא לה כך, ובמקרה של בעיה מדווחים onError.onPreExecute: רצה לפני doInBackground, גם בתרד ה-UI. קוראת ל-listener.onAboutToStart() כדי להודיע ל-Activity שהעבודה עומדת להתחיל.Callbacks מכיל עכשיו onAboutToStart ו-onSuccess במקום onFinish. ה-constructor מקבל רק את ה-callbacks.PrimesFinder עם this וקוראים ל-execute(start, end). אין צורך ב-Thread או ב-start.onPreExecute (UI), אחר כך doInBackground (תרד נפרד, ה-UI משוחרר), ובסוף onPostExecute (UI) עם התוצאה.הטקסט המלא של הדקות הראשונות בהרצאה «הסבר על Async Task» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.
ראשר ראינו שתרד פותר בעיה אסינכרונית ומאפשר להריץ את הקוד בצורה אסינכרונית ולכן ה-UI לא נתקע למשתמש, אבל הוא לא פותר את בעיית עדכון ה-UI, והתוכנית כמובן קורסת אם הטרד מנסה להדכן את ה-UI, אנחנו יכולים לעבור לעבודה עם AsyncTask שבעצם פותרת את שתי הבעיות האלה, גם מאפשרת להריץ קוד אסינכרוני על ידי
תרד נפרד, אבל גם מאפשרת להדכן את ה-UI. אז בואו נראה איך עושים את זה. יש לנו כאן את המחלקה Primes Finder שבנינו מקודם, וPrimes Finder ירשה או ממשה ליתר דיוק את Runnable עבור התרד.
אנחנו לא עושים את זה, בואו נמחק את זה. ומה שאנחנו צריכים לעשות זה לרשת את AsyncTask. עכשיו, למחלקה AsyncTask זאת מחלקה שהיא Generic.
זה אומר שאנחנו צריכים על ידי הסוגיים המשולשים להגדיר מה סוגים השונים של המידע שאנחנו עובדים איתם. מחלקה שהיא Generic יכולה להגדיר אחד או יותר, תלוי אכבנו אותה, ואסינג טאסק מגדירה שלושה טיפוסים ג'נריים שאנחנו צריכים לעבוד איתם בתוך הפעילות הפנימית של המחלקה.
אז הטיפוס הראשון שהמחלקה הזאת צריכה להגדיר זה מה המידע שהיא מקבלת מבחוץ. אם אנחנו מסתכלים על מה אנחנו רוצים לשלוח למחלקה, זה יהיה את המספר ההתחלתי ואת המספר הסופי שהטיפוסים שלהם זה long.
אז אנחנו צריכים להגדיר כאן long, אבל אנחנו לא מגדירים את זה בצורה כזאת, אלא מגדירים את זה כטיפוס long עם עוד ראשונה גדולה. הטיפוס השני שאנחנו צריכים להגדיר זה מה הטיפוס נתונים שהמחלקה מדווחת לעולם החיצון תוך כדי הפעילות הפנימית של המחלקה.
כאשר אנחנו יכולים לדווח, לדוגמה, אחוז חישוב שיסתיים, אנחנו יכולים לדווח מכרוזות שמתארות מה בדיוק סיימנו, אנחנו מחליטים מה אנחנו רוצים לדווח, ובתור התחלה אני לא רוצה לעשות את זה יותר מדי מורכב, ולכן אנחנו לא נדווח כלום, אז זה יהיה וויד.
בסרטון אחרי זה אנחנו כמובן כן נגדיל את זה ונדווח דברים. עכשיו אנחנו צריכים להגדיר את הטיפוס השלישי והטיפוס השלישי ומה בדיוק המחלקה מחזירה לעולם החיצון כתוצאה סופית של הפעילות שלה.
ואם נסתכל על מה Tread דיווח אז אנחנו נראה שהוא דיווח את הסטרינג הזה בתור תוצאה סופית כי הוא אסף את כל המספרים הראשוניים לסטרינג אחד ובסוף נתן את הסטרינג הזה. אז בדיוק הסטרינג הזה אנחנו רוצים לדווח כאן כטיפוס אחרון אז בואו רגע ניפטר מכל מיני דברים שהיו לנו כאן אנחנו לא נצטרך את השני טיפוסים האלה את ה-callbacks אנחנו כן נצטרך
אין לנו פה את הקונסטרקטור הזה יש לנו למעשה, לא בעצם יש לנו קונסטרקטור אבל הקונסטרקטור צריך לקבל רק את ה-callbacks אנחנו כן רוצים לדווח דברים, אין לנו את ה-end ואת ה-start האלה כאן, פונקציית run כמובן לא נמצאת, תכף אנחנו ניפטר ממנה, וה-interface כן קיים לנו.
ומה שאנחנו רוצים לעשות זה לממש פונקציה אחת שחובה לממש אותה, והפונקציה הזאת נקראת doInBackground. בואו נממש אותה ומה שהפונקציה הזאת אומרת זה אני פועלת בתרד נפרד invoked in a different thread thus can't touch the UI ונקודה מאוד מאוד חשובה הפונקציה הזאת doing background תופעל אוטומטית כאשר אנחנו בעצם נריץ את המחלקה הזאת
והפונקציה הזאת תתבצע בתרד נפרד ואם היא מתבצעת בטרד נפרד, אסור לה לגעת ב-UI של המחלקה בסוף הפעילות של הפונקציה, כלומר את כל הפעילות אנחנו מבצעים בפונקציה הזאת כל הפעילות הזאת היא מלולהה שלוקחת הרבה זמן אבל אסור יהיה לנו בתוך הפונקציה להשתמש באינטרפייס בשביל לדווח למעין אקטיביטי את המספר הסופי או ליתר דיוק את המכרוזת הסופית
בפני שאם אנחנו נעשה את זה, עוד פעם אנחנו נקבל קריסה. אז איפה אנחנו צריכים לדווח? אנחנו צריכים לדווח בפונקציה אחרת שנקראת onPostExecute.
onPostExecute זאת פונקציה שתופעל אוטומטית בסיום הפעילות, אבל היא כן תורץ בטרד של ה-UI. וזה מה שמיוחד ויפה ב-AsyncTask. AsyncTask מכילה לנו בתוכה מספר פונקציות, פונקציה אחת DoingBackground רצה בטרד נפרד ומאפשרת לבצע פעילות במקביל ופונקציה אחרת OnPostExecute, כאשר המילה פוסט זה אחרי, אחרי שהאקסקיוט יתבצע והסתיים אנחנו יכולים לבצע
פה קוד שכן ירוץ בטרד של ה-UI, Invoked in the UI's thread. ולכן כן אנחנו יכולים לגעת ב-UI ופה בעצם אנחנו רוצים לדווח את הסיום של הפעילות אז אנחנו לא נקרא לזה רק on finish, אנחנו נקרא לזה on success מפני שיכול להיות שיש לנו איזושהי בעיה באמצע ואנחנו נרצה לדווח on arrow באלגוריתם הזה לא תהיה בעיה
מפני שלמצוא מספרים ראשונים אין קריסה מסוימת שהולכת להתרחש באמצע אבל בכל מקרה מקובל שזה יהיה onSuccess, ואם יש איזושהי בעיה, אז אנחנו מדווחים onError מסוים.
אוקיי, אז בואו פשוט נדווח את onSuccess, זה נמצא ב-Listener, onSuccess, ונשלח את ה-String, כאשר ה-String נקרא לה Result, onS, וזה התוצאה הסופית של החישוב.
עכשיו קיימת עוד פונקציה שאנחנו יכולים לדרוס, והפונקציה שקיימת בנוסף נקראת onPre-Execute. וonPre-Execute מתבצעת לפני onDoingBackground, יש לנו את onPre, doingBackground וonPost.
וonPre מתבצעת גם היא בטרד של ה-UI, ולכן היא יכולה לגעת ב-UI. מה אנחנו רוצים לעשות בתוך הפונקציה on pre, אנחנו רוצים לדווח שאנחנו הולכים להתחיל, עוד לא באמת התחלנו את התהליך, אנחנו ממש עוד שנייה הולכים להתחיל את התהליך, אז בואו נבנה פה איזושהי פונקציה שנקראת on about to start, והפונקציה on about to start לא צריכה
לקבל שום דבר, ובתוך on pre execute, כאשר pre בהקשר הזה זה לפני, נרשום listener, on about to start, ואז בעצם אנחנו מציינים למיין אקטיביטי שאנחנו ממש הולכים