PracticU

Save Collection to Text File

בלי כתוביותעם כתוביות
PracticU › קורס פיתוח אפליקציות - לאנדרואיד - Android - ב-JAVA › Save Collection to Text File
מילון מושגים:
אובייקט - יחידה בתכנות מונחה עצמים שמאגדת נתונים (תכונות) ופעולות (מתודות). נוצר בדרך כלל ממחלקה המשמשת כתבנית.
מחלקה - תבנית בתכנות מונחה עצמים שמגדירה אילו נתונים ופעולות יהיו לאובייקטים שנוצרים ממנה.
Activity - ב-Android, רכיב שמייצג מסך יחיד של האפליקציה שאיתו המשתמש מתקשר.
נתיב - מחרוזת שמתארת את מיקומו של קובץ או תיקייה במערכת הקבצים, או כתובת של משאב בתוך אתר.
ArrayList - מבנה נתונים של רשימה דינמית שגודלה משתנה, הנפוץ בשפות כמו Java ו-C#.
חריגה - מצב שגיאה שמתרחש בזמן ריצת התוכנית ומפסיק את המהלך הרגיל, אלא אם הקוד תופס ומטפל בו.
Integer - סוג נתונים למספר שלם, כלומר מספר ללא חלק עשרוני.
לולאה - מבנה בקרה שחוזר על קטע קוד שוב ושוב כל עוד תנאי מתקיים או עבור כל פריט באוסף.

Save Collection to Text File
איך שומרים אוסף של אובייקטים לקובץ טקסט וטוענים אותו בחזרה, כך שהמשתמש לא מאבד את הנתונים בין הרצות? בשיעור מוסיפים שמירה וטעינה לאפליקציית מוצרים קיימת.
האפליקציה
האפליקציה מציגה ב-ListView רשימת מוצרים (id, name, price) עם כותרת שסופרת אותם. ה-id נוצר אוטומטית ממשתנה סטטי. המחלקה Product היא Serializable, ויש Activity להוספת מוצר, ProductAdapter מותאם, ותפריט להוספה וליציאה. בהתחלה אין שמירה, ולכן אחרי סגירה כל המוצרים נעלמים.
המחלקה TextFileManager
1. נתיב הקובץ: פונקציה סטטית שמחזירה MyApp.getContext().getFilesDir().getAbsolutePath() ועוד /products.txt, לשימוש גם בשמירה וגם בטעינה.
2. save: מקבלת ArrayList<Product> ופותחת FileWriter. הפונקציה מצהירה על throws Exception ולא תופסת אותה, כי המחלקה אינה Activity ואין לה איך להציג הודעה למשתמש. היא משתמשת ב-try finally רק כדי לסגור את הקובץ. קבוע NEW_LINE (\r\n) מונע טעויות.
3. הפורמט שהוחלט עליו: שורה ראשונה היא מספר המוצרים (products.size()), ואחריה לכל מוצר שלוש שורות: id, name, price. כך נוח לקרוא: קודם את הכמות, ואז בלולאת for רגילה.
4. load: הפונקציה ציבורית ומחזירה ArrayList<Product>. אם הקובץ לא קיים (הרצה ראשונה), מוחזרת רשימה ריקה. אחרת פותחים FileReader ו-BufferedReader, קוראים את הכמות עם Integer.parseInt, ובלולאה קוראים id, name ו-price (Double.parseDouble), יוצרים Product ומוסיפים לרשימה.
חיבור ל-MainActivity
- ב-onCreate במקום ליצור רשימה ריקה קוראים ל-TextFileManager.load(), בתוך try catch שמציג Toast עם הודעת השגיאה.
- השמירה נעשית ב-onStop, כי המשתמש יכול לסגור את האפליקציה גם בלי לבחור "exit" מהתפריט, למשל מ-Recent apps. גם היא בתוך try catch.
בדיקה
אחרי הוספת מוצרים ויציאה, הרשימה נטענה מחדש. אחרי הוספת מוצר רביעי והרצה חוזרת, גם הוא נשמר. בקובץ שנשלף מ-DDMS רואים את מספר המוצרים ואחריו שלשות של שורות.
כעת אפשר לשמור ולטעון אוסף אובייקטים בקובץ טקסט בפורמט שאנחנו מגדירים בעצמנו.
השיעור הבא בקורס: Save Collection to Binary File

פרקי ההרצאה: Save Collection to Text File

  1. 00:00

    דוגמת אפליקציה לניהול מוצרים

  2. 01:01

    המחלקה Product כ-Serializable

  3. 01:41

    Activity להוספת מוצר ו-Custom Adapter

  4. 04:01

    הרצה והוספת מוצרים לרשימה

  5. 05:24

    יצירת המחלקה TextFileManager

  6. 07:25

    זריקת חריגה בחתימת הפונקציה

  7. 09:48

    שמירת המוצרים לקובץ בלולאה

  8. 11:34

    שמירת מספר הפריטים בתחילת הקובץ

תמלול ההרצאה: Save Collection to Text File

הטקסט המלא של הדקות הראשונות בהרצאה «Save Collection to Text File» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.

  1. 00:02

    אחרי שראינו איך אנחנו יכולים לשמור מידע בקובץ ולקרוא מידע מקובץ בואו נעבור לדוגמה יותר אמיתית שבאמת יכולה להיות באפליקציה שלכם ושמכילה נתונים קצת יותר מורכבים לדוגמה קולקשן ונראה איך אנחנו יכולים לשמור אותה ולטעון אותה במספר דרכים.

  2. 00:26

    הדבר הראשון שאנחנו הולכים לעשות זה לעבור על הדוגמה הזאתי, זו דוגמה מוכנה אבל שהיא רק כרגע לא מבצעת שמירת מידע וטעינת מידע מקבצים, ואנחנו רק הולכים להוסיף את זה בסרטון הזה ובסרטונים הבאים.

  3. 00:41

    אז קודם כל יש לנו כאן את המיין אקטיביטי, ובמיין אקטיביטי סך הכל מה שאנחנו רואים כאן זה איזושהי כותרת שמציגה כמה מוצרים יש לנו, הדוגמה בעצם מתעסקת עם מוצרים, ויש לנו ליסט view שמציגה את רשימת המוצרים.

  4. 01:01

    יש לנו כאן איזושהי מחלקה שמתארת מוצר בודד ולמוצר יש ID, Name ו-Price כאשר ה-ID מיוצר אוטומטית על ידי משתנה סטטי שנקרא ID Generator שכל פעם אנחנו מוסיפים לו אחד.

  5. 01:22

    אז יש לנו כאן ID, Name ו-Price עבור כל מוצר. שימו לב שהמחלקה הזאת מוגדרת כ-Serializable וזה מאפשר לדוגמה לשלוח אותה מ-activity א' ל-activity ב', לדוגמה לשמור אותה על ידי קובץ בינארי, מנגנון ה-serialization ועוד.

  6. 01:45

    הדבר הבא שיש לנו זה איזושהי אקטיביטי נוספת שמאפשרת לנו לקבל מהמשתמש מוצר אחד. המשתמש מכניס רק name ו-price, כאמור ה-ID מיוצר לו אוטומטית כמספר רץ והוא יכול לבצע אד ולהוסיף את המוצר הזה לרשימת המוצרים.

  7. 02:10

    יש לנו כאן איזשהו layout שמאפשר לנו לראות מוצר בודד, אנחנו רואים את ה-ID, אנחנו רואים את השם ואנחנו רואים את המחיר ויש לנו איזשהו custom adapter, product adapter הוא נקרא, שיורש מהרי אדפטר בכדי לקחת אריי ליסט של מוצרים ולהציג אותם בלייאוט המיוחד הזה שראינו.

  8. 02:39

    מה יש לנו במיין אקטיביטי? במיין אקטיביטי יש לנו סך הכל את האריי ליסט של המוצרים, יש לנו את האדפטר, יש לנו את הרכיבים הוויזואליים, את הכותרת ואת הליסט view, יש לנו איזשהו request code בכדי להציג את ה-activity שמקבל את המוצר.

  9. 03:04

    כאן אנחנו מקבלים, מאתרים בעצם את הרכיבים הוויזואליים, את ה-list view ואת ה-header הזה, שזה נקרא ה-text view count, יוצרים אובייקט array list, אובייקט אדפטר, מקשרים אותם, מציגים באיזושהי פונקציה כמה מוצרים יש.

  10. 03:24

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

  11. 03:58

    המוצר כי הוא סריאליזבל, מוסיפים אותו לאוסף, מרפרשים את הליסט ואת ההדר. בואו נריץ ונראה איך כל הסיפור הזה עובד.

  12. 04:12

    אז בהתחלה כאשר אנחנו מריצים אין לנו בכלל מוצרים ואנחנו רוצים לגשת ולהוסיף מוצר, נגדיר כאן green apple, 3.5, נבצע הוספה והנה אנחנו רואים מוצר אחד ויחיד.

  13. 04:30

    בואו נוסיף round pitch שעולה 4.7 ובואו נוסיף עוד מוצר, נוסיף sweet banana ו-sweet banana עולה 5.2 ובואו נוסיף אותו ויש לנו עכשיו שלושה מוצרים.

  14. 04:57

    אם אנחנו עכשיו יוצאים החוצה מהמערכת, אפליקציה לגמרי ונכנסים אליה עוד פעם אז לא שמרנו את המידע וכמובן שאנחנו לא יכולים לקרוא אותו לא טענו אותו גם והוא לא שמור בשום מקום ואנחנו רוצים בדוגמה הזאת להראות בהתאם לכל מה שלמדנו בנוגע לקבצים איך אנחנו יכולים לשמור את המידע הזה בקובץ ולטעון אותו בחזרה.

  15. 05:27

    אז בסרטון הזה מה שאנחנו הולכים לעשות זה לשמור הכל לקובץ טקסטואלי. לצורך כך בואו נוסיף מחלקה חדשה ונקרא לה טקסט פייל מנג'ר.

  16. 05:42

    המחלקה הזאת תוכל לנהל את כל השמירה והתאנה של המידע. הדבר הראשון שאנחנו רוצים לעשות זה לבנות איזושהי פונקציה סטטית תחזיר לנו את הנתיב ואת השם של הקובץ כי אנחנו רוצים להשתמש עם זה גם בשמירה וגם בטעינה.

  17. 06:11

    אז אנחנו רוצים להחזיר את myapp, ש-myapp זה הקונטקסט שלנו, קונטקסט גלובלי כזה שאנחנו כבר מכירים איך עושים את זה. אנחנו רוצים להחזיר את myapp, הוא נעלם לי, הנה הוא פה, נקודה get context בכדי להגיע ל-get files dir כי אנחנו לא אקטיביטי בעצמנו.

  18. 06:37

    משם אנחנו רוצים להגיע ל-get absolute path ובואו נשרשר כאן את products.txt והנה יש לנו כבר פונקציה שמסוגלת להחזיר את הנתיב לקובץ.

  19. 06:53

    עכשיו אנחנו רוצים פונקציה סטטית שנקראת סייב והיא תהיה מסוגלת לקבל אריי ליסט של מוצרים נקרא לו פרודקטס ופשוט לשמור את כולו לקובץ טקסטואלי אז יש לנו פה פייל רייטר נכניס לתוכו נאל ואנחנו רוצים לבנות אובייקט מהפייל רייטר שווה ניו פייל רייטר להגיע לגט פאת'ן פייל ניים אנחנו מקבלים בחזרה את

  20. 07:30

    השם של הפונקציה ועכשיו אנחנו בעצם רואים שהמערכת אומרת לנו שיש לנו כאן זריקת חריגה מתוך הפייל רייטר. אז או שנוסיף טרייקאץ', סראונד וויד טרייקאץ', או שנגרום לפונקציה שלנו לדווח על אקספשן בסיגנצ'ר, בחתימה שלה.

  21. 07:56

    למה אנחנו לא רוצים לעטוף ב-try catch מפני ש-catch מבצעים באותו מקום שמסוגל לטפל בבעיה אבל בגלל שאנחנו איזושהי מחלקה פנימית יותר אנחנו לא אקטיביטי בעצמנו אז קורה לפעמים שאין לנו בדיוק מה לעשות ב-catch כי ב-catch בדרך כלל נציג הודעת שגיאה ליוזר לא תמיד אבל לפעמים אין לנו מה להציג פה הודעת שגיאה ליוזר כי

  22. 08:23

    אנחנו לא אקטיביטי הודעות שגיאה מציגים באקטיביטי אז אנחנו לא רוצים לחשום פה catch, אנחנו רוצים לבצע פה איזשהו signature ולהגדיר שאנחנו פשוט זורקים חריגה.

  23. 08:39

    ומי שיקרא לנו, זה בעצם ה-activity, היא תצטרך לבצע את ה-try catch האמיתי. מה אנחנו כן רוצים לעשות? אנחנו כן רוצים לבצע try finally.

  24. 08:56

    למה? כי גם אם יש exception אנחנו עדיין רוצים לבצע את הסגירות שדיברנו עליהן. אז זה בעצם דיזיין יותר מתאים במקרה הזה. אם אנחנו שונים מנ"ל בואו נבצע close בצורה כזאת.

  25. 09:15

    אין לנו צורך פה ב-try catch כי אנחנו מדווחים שאנחנו זורקים exception. אז המערכת יכולה לקרוס לדוגמה אם הקובץ כבר נמצא בשימוש, אבל אז אנחנו זורקים אקספשן ומי שמשתמש בנו יצטרך לטפל בו.

  26. 09:33

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

  27. 09:48

    אז אנחנו פשוט יכולים לרוץ באיזושהי לולאת for each product p in product, נשים את זה רק באותה השורה ולהתחיל לשמור את המידע שיש לנו בקובץ פייל רייטר בוא נרשום את pgetid קודם כל נשכפל את זה ל-getname ול-getprice ואנחנו רוצים לרדת שורה בכל אחד מהם.

  28. 10:33

    אז נשרשר כאן את ה-בקסלש r, בקסלש n עבור כל אחד מהחברייה האלה. עכשיו, הרבה פעמים אולי כדאי לבצע איזשהו קבוע גלובלי כזה, private final static string נקרא לו new line, נכניס בקסלש r, בקסלש n, ואז קצת יותר אלגנטי שאנחנו משרשרים פה את

  29. 11:08

    הקבוע new line ולא מתחילים להתעסק עם מכרוזות בצורה כזאת שפעם אנחנו נשכח ונעשה backslash n בלי backslash r וכל מיני כאלה. אז הנה יש לנו פה משהו קצת יותר אלגנטי.

  30. 11:22

    אז מה שעשינו זה רצנו על כל האוסף ופשוט שמרנו לכל אובייקט את ה-id, name ו-price שלו בשלוש שורות נפרדות.

  31. 11:35

    עכשיו, בגלל שאנחנו מייצרים את הקובץ הזה ואנחנו ממציאים פה פורמט משלנו, לדוגמה אנחנו קובעים שה-ID נמצא ראשון ולא שני, או שאחרי ה-ID בא ה-Name ולא ה-Price, אז אנחנו יכולים לשלוט על הפורמט הזה ולהחליט, לדוגמה, שהדבר הראשון שאנחנו שומרים זה את product.size למה?

  32. 12:07

    כי אנחנו רוצים שיהיה לנו מאוד נוח לקרוא את הקובץ, כי זה אותו פורמט שאנחנו ממציאים עבור הכתיבה, אנחנו גם צריכים לקרוא אותו. אז ככה אנחנו יכולים להחליט שהשורה הראשונה הראשונה שיש בקובץ זה פשוט כמה פריטים יש, בכדי שכאשר נקרא את הקובץ, קודם כל נקרא את המספר הזה ואז נוכל לרוץ עליו בלולת for רגילה.

  33. 12:33

    אוקיי, אז הנה יש לנו כאן את פונקציית ה-save, ואנחנו יכולים לגשת ולבנות את פונקציית ה-load. יש לנו פה private,

לקורס המלא: קורס פיתוח אפליקציות לאנדרואיד

ההרצאה הקודמת: Object Serialization

ההרצאה הבאה: Save Collection to Binary File

הרצאות קשורות מקורסים אחרים

  • יצירת Collection
  • הגדרת Query Collection
  • transaction save point
  • Importing File

קורסים נוספים במסלול

  • קורס יסודות התכנות - שפת JAVA - קורס ג'אווה למתחילים
  • קורס פיתוח אפליקציות - לאייפון iPhone iOS - ב-Swift-Xcode
  • קורס פלאטר - Flutter - שפת DART של גוגל למובייל - פיתוח אפליקציות לאנדרואיד ואייפון
  • קורס PhoneGap - פיתוח אפליקציות לאנדרואיד ואייפון