
ImageDownloader כך שיקרא את התמונה בחבילות ויציג אחוז הורדה.AsyncTask כותבים Integer במקום Void, כי מדווחים אחוזים.connection.getContentLength() מחזיר את גודלה בבתים. יוצרים מערך בתים (imageArray) בדיוק בגודל הזה.currentBytesRead הוא כמה בתים נקראו בקריאה האחרונה, ו-totalBytesRead הוא הסכום עד כה. שניהם מתחילים ב-0. bytesToRead הוא כמה רוצים לקרוא, שונה מכמה נקרא בפועל.PACKET עם הערך 1024. אם גודל התמונה קטן מחבילה, קוראים רק את גודלה, ואחרת חבילה.inputStream.read(imageArray, offset, bytesToRead) מחזירה את מספר הבתים שנקראו, או -1 כשנגמר. בלולאה while כל עוד התוצאה שונה מ-1-, מוסיפים אותה ל-totalBytesRead וקוראים את החבילה הבאה מהאופסט totalBytesRead. אם נשאר פחות מחבילה, bytesToRead הוא imageSize - totalBytesRead.BitmapFactory.decodeByteArray ממיר את המערך ל-Bitmap.totalBytesRead * 100.0 / imageSize כ-int. מדווחים אותו עם publishProgress ולא ישירות מ-doInBackground, שבה אסור לגעת ב-UI. percentReported מונע דיווח חוזר של אותו אחוז.onProgressUpdate ומקבלים את values[0]. מוסיפים ל-listener את onUpdateProgress, וב-Activity מעדכנים עם progressDialog.setProgress(percentDone).ProgressDialog קוראים ל-setProgressStyle(ProgressDialog.STYLE_HORIZONTAL), כדי שיהיה פס אופקי ולא עיגול מסתובב.הטקסט המלא של הדקות הראשונות בהרצאה «Download Image in Packets» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.
כאשר אנחנו גולשים ב-API ומורידים טקסט, אז ברוב המקרים המידע הטקסטואלי שאנחנו מורידים הוא לא מאוד גדול ולכן ההורדה הזאת היא מאוד מהירה. אבל כאשר אנחנו גולשים לאיזשהו API שמביא לנו תמונה או גולשים לאיזשהו קובץ מרוחק של תמונה, יכול להיות שהתמונה היא די גדולה ולכן ההורדה תיקח זמן.
אם ההורדה תיקח זמן כמובן שהיוזר יצטרך להמתין ובעצם הוא יראה את אותה דיאלוג מסתובבת והוא לא ממש יודע כמה זמן נשאר לו. אז אנחנו הולכים לשדרג את האפליקציה הקודמת שבנינו שמורידה תמונה כך שההורדה תדע לדווח ליוזר בכל רגע ורבע כמה אחוז חישוב כבר הסתיים.
איך אנחנו יכולים להצטיח לבצע את זה? אז קודם כל בואו ניגש לאימג' דאונלודר ומה שאנחנו רוצים לעשות זה במקום הוויד כאן אנחנו רוצים לרשום אינטג'ר כי אנחנו רוצים לדווח את אחוז החישוב שמסתיים כל רגע.
הדבר הבא שאנחנו רוצים לעשות זה לגשת כאן למטה ויש לנו כאן את האינפוט סטרים ואנחנו רוצים עכשיו להתחיל לקרוא את המידע של התמונה דרך הסטרים אבל אנחנו לא רוצים בבת אחת להפוך את הכל לתמונה מה שלוקח הרבה זמן אלא אנחנו רוצים לקרוא חלקים חלקים מהתמונה ואנחנו רוצים כל הזמן לדווח ליוזר כמה אחוז חישוב כבר הסתיים מההורדה שלנו אז בואו נראה איך אנחנו יכולים לעשות את זה
הדבר הראשון שאנחנו רוצים לקחת בדיוק בנקודה הזאת זה את הגודל של התמונה יש לנו פה משתנה image size ואנחנו יכולים להשיג את הגודל על ידי connection.getContentLength זאת פונקציה שמחזירה לנו כמה גודל ה-content בעצם שיש לנו לקרוא בבתים אז יש לנו עכשיו את הגודל בבתים ומה שאנחנו צריכים לעשות זה לפתוח מערך בתים, בואו נקרא לו image array
ולהתחיל להכלס אותו במידע שאנחנו מורידים תוך כדי ההורדה אז בואו נייצר פה new byte array ואנחנו רוצים שהגודל שלו יהיה בדיוק הגודל של התמונה שכרגע הסטרים אמר לנו הדבר הבא שאנחנו רוצים זה לפתוח משתנה, integerי, בואו נקרא לו current bytes red וזה כמה בעצם בתים אנחנו קראנו לאחרונה, כלומר
הקריאה הנוכחית כמה בתים קראנו ומשתנה נוסף שנקרא TotalBytesRed בואו נכניס לשניהם 0, נאפס אותם על ההתחלה והTotalBytesRed כמובן כשמו כן הוא יגיד לנו כמה בתים סך הכל כבר קראנו כעת אנחנו רוצים לגשת ולדעת כמה בעצם אנחנו רוצים לקרוא bytes to read כמה בעצם אנחנו רוצים לבוא ולומר שאנחנו רוצים להחזיר מהסטרים ויש הבדל בין bytes to read
שזה כמה אנחנו רוצים לבין current bytes read שזה כמה בפועל הצלחנו לקרוא כי יכול להיות שאנחנו רוצים לקרוא בוא נניח 100 בתים אבל אין 100 בתים לתמונה יש רק 97 בתים נניח ולכן כאן אנחנו בעצם רוצים לדעת כמה בעצם אנחנו רוצים עכשיו לקרוא.
אז קודם כל אנחנו צריכים להחליט מה הגודל של כל פקטה שאנחנו קוראים. פקטה זה בעצם חבילה אחת של בתים שאנחנו רוצים לקרוא. ובואו ניקח את המספר 1024 שזה מספר נפוץ עבור פקטות.
אז בשלב הזה נעלה כאן למעלה ונייצר private final static packet ניתן לו, קודם כל הוא צריך להיות כמובן integer וניתן לו 1024 ונשתמש עם הקבוע הזה בכל מקום, ככה בהמשך נוכל פשוט לשנות את גודל הפקטה אם נרצה אז אנחנו בעצם רוצים לדעת כמה בתים עלינו לקרוא ואנחנו יכולים לבצע חישוב האם image size יותר קטן מפקט אם כן אנחנו רוצים לקרוא רק את הimage size
אם לא אנחנו רוצים לקרוא את גודל הפקט נניח שיש לנו תמונה שהיא במקרה יותר קטנה מהפקטות אז אנחנו רוצים לקרוא רק את הגודל של התמונה עכשיו אנחנו רוצים לבצע את הקריאה העצמה זה יהיה current bytes red כמה באמת בתים אנחנו הולכים לקרוא דרך האינפוט סטרים יש לנו פונקציה שנקראת read הפונקציה אומרת לנו תביאו לי מערך
בואו רגע נלחץ Ctrl-P ונראה מה היא מבקשת היא אומרת לנו תביאו לי מערך שלתוכו אני אכניס את המידע זה יהיה ה-image הרי שבנינו מאיזה מקום אתם רוצים שאני אכלס את המערך שלכם כמובן מההתחלה כי זה פעם ראשונה שאנחנו קוראים וכמה אתם רוצים שאני אקרא מהסטרים זה יהיה bytes to read
עכשיו אם הפונקציה הזאת מצליחה לבצע את הקריאה והכל בסדר אז היא מחזירה לנו כמה בתים היא הצליחה לקרוא אם לא אז היא מחזירה מינוס 1 אז אנחנו יכולים עכשיו לרוץ בלולאה colored current bytes read שונה ממינוס 1 הייתה קריאה שהצליחה להתבצע אם הייתה קריאה שהצליחה להתבצע אז אנחנו עכשיו רוצים להוסיף
לטוטל בייטס רד, בואו נוסיף לו על ידי פלוס שווה, את קורנט בייטס רד, ואנחנו רוצים עכשיו לגשת ולדעת כמה עוד בתים אנחנו רוצים לקרוא, כי אנחנו רוצים להמשיך את הקריאה.
אז זה יהיה בייטס טו רד, ועכשיו אנחנו רוצים לבדוק האם האימג' סייז יותר קטנה מהטוטל בייטס רד, ועוד כמה פקטות שאנחנו, או כמה פקטה אחת אז Total Bytes Red פלוס פקטה אחת האם גודל התמונה קטן יותר אז זאת אומרת שיש לנו עדיין לקרוא פקטות מהתמונה אז בואו נקרא את Image Size
פחות Total Bytes Red במילים אחרות, אם גודל התמונה או מספר הבתים שנשאר לנו לקרוא הוא קטן יותר מפקטה אחת, אז אני לא רוצה לקרוא פקטה אחת, כי אין לי בעצם גודל של פקטה.
אני רוצה לקרוא כמה שנשאר לי. כמה שנשאר לי זה image5, פחות כמה שכבר קראנו. אוקיי, אם לא, בואו נקרא פקטה אחת. ויש לנו עכשיו שוב פעם bytes to red.
הדבר הבא שאנחנו רוצים לעשות זה שוב פעם לגשת ולהוסיף אותו, או לבצע את הקריאה עצמה. current bytes read, שווה שוב