אנדישבוע מ צ ו י י ן ! לכל תלמידי האקדמיה!
וברוכים השבים לשיעור השלישי, בקורס השלישי, באקדמיה ללימודי פיתוח באנדרואיד !

השבוע אנחנו נקשר בין הרכיבים הגראפיים שהגדרנו בעורך הויזואלי ו/או בקוד ה- XML בשיעור הקודם לבין הקוד האמיתי שבתוכנה שלנו.

טוב להיות פה גם השבוע, אנדי!

אנדיוטוב לראות גם אותך איתנו,
ברק הברוקולי :)

רגע רגע! אני רוצה להבין! אתם החלפתם אותי בירק!??

אנדיהמורה?
את לא אמורה להיות בשביתה?

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

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

וזה מה שאתם מעדיפים לשמוע וללמוד?

אנדיהאמת, למה לא?
הוא דווקא דמות מאד נעימה וחביבה.

אליעזר בן יהודה פשוט מתהפך בקיברו! בושה וחרפה ללשון ולדבורה!

אנדיאיזה דבורה? על מה את מדברת? עוד לא התחלנו את השיעור וכבר הכל בבלאגאן?
די! בואו בבקשה נתחיל את השיעור שלנו.

חיבור בין הקוד לרכיבים הגראפיים

טוב, אז במשך שני שיעורים שאנחנו מדברים על רכיבים גראפיים, על Widgets, על הגדרתם בקובץ XML, על העורך הויזואלי…

הכל טוב ויפה, אבל אתם בטח מתגעגעים לקודד. איך אנחנו בעצם לוקחים את הרכיבים שהגדרנו ומשתמשים בהם בקוד?
בשיעור הקודם הסברתי שה- Layout והרכיבים בתוכו הם בעצם משאבים. אם נחזור עוד קצת אחורה, לשיעור *משאבים ותמונות, נזכר כי ה- Resource Compiler יוצר לנו מחלקה בשם R שמחזיקה את כל המשאבים שלנו.

כלומר אם הגדרנו Widget מסויים (לדוגמא TextView או Button) ואנחנו רוצים לגשת אליו, נוכל לעשות זאת דרך המחלקה R.

אבל אנדי, מה קורה אם יש לנו יותר מ- TextView אחד או יותר מכפתור (Button) אחד? איך נדע לזהות את הרכיב הגראפי הנכון?

אנדישאלה פשוט מצויינת ברק!
בשיעור מבוא ל XML ושימוש ברכיבים גראפיים, דיברנו על כך שלרכיבים יש מאפיין בשם android:id, שהוא מאפיין מיוחד המזהה את הרכיב ונוכל להשתמש בו כדי למצוא את הרכיב הגראפי.

מחקנו אותו בשיעור הקודם, אבל עכשיו הגיע הזמן להציג אותו מחדש!
בואו נחזיר אותו ל- main.xml שלנו:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical" android:layout_width="fill_parent"
	android:layout_height="fill_parent" android:background="#FFF">

	<TextView android:text="iAndroid Academy Rules!"
		      android:id="@+id/TextView01"
			  android:layout_width="wrap_content"
			  android:layout_height="wrap_content"
			  android:textColor="#50AB86" />
</LinearLayout>
<pre>

המאפיין android:id מופיע בשורה 7. הצורה שבה הוא מוגדר מעניינת במיוחד, בואו ננסה להבין מה קורה פה.
למעשה מה שאנחנו רוצים לעשות פה זה להגדיר לאובייקט ה- TextView איזשהו מזהה, שבאמצעותו נוכל לגשת אליו ספציפית בקוד שלנו.
התו '@' בתחילת המחרוזת מסמן למהדר להתייחס ל- TextView01 כאל שם של המזהה המגדיר את האובייקט הנוכחי.
התו '+' מסמן למהדר שזהו מזהה חדש, שהוא צריך ליצור ולהוסיף למחלקה המיוחדת R, על מנת שנוכל להשתמש בשם המזהה הזה בקוד שלנו.

עכשיו בואו נראה איך משתמשים בו בקוד:

בפרויקט שיצרנו בשיעור שעבר, הכנסו לקוד של ה- Activity שלכם, והוסיפו את השורות הבאות בתוך המתודה onCreate:

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        TextView myTextView = (TextView)findViewById(R.id.TextView01);

       myTextView.setBackgroundColor(Color.YELLOW);
    }

שימו לב, רק שורות 5 ו- 7 התווספו, שאר השורות היו שם כבר מקודם.

שורה 5: שורה המכילה הרבה מונחים חדשים, אז נעבור עליה בקפידה.
דבר ראשון, אנו מגדירים עצם חדש בשם myTextView מסוג TextView.

לאחר מכן, אנו קוראים למתודה findViewByID שיודעת "למצוא" לנו View בתוך המשאב שלנו, בעזרת ה- ID שלו. למה השם של המתודה היא findView ולא findWidget לדוגמא?
גם כאן אני מזכיר לכם, כל רכיב גראפי (וכל Widget) בעצם יורש מתוך מחלקת האב View. מחלקת האב View היא המשותפת לכולם, ולכן במקום ליצור מתודה נפרדת לכל סוג של View שמחזירה אותו, ניתן פשוט להגדיר את האובייקט המוחזר מטיפוס מחלקת הבסיס.
אבל ההגדרה הזו אינה משנה את הטיפוס האמיתי של האובייקט, ולכן אנחנו יכלים להסב אותו לאובייקט מטיפוס מחלקת הבת, כדי לחשוף את המאפיינים הספציפיים והמתודות של מחלקת הבת.

התהליך הזה נקרא Type Casting, כאשר קיימים 2 סוגים של Type Casting: Explicit Type Casting שבו אנחנו צריכים לציין את הטיפוס שאליו אנחנו מבצעים את ההסבה, כמו בדוגמא של אנדי, ו- Implicit Type Casting שבו ההסבה מבוצעת באופן אוטומטי בלי שנצטרך להצהיר על כך במפורש. ככלל Explicit Type Casting יש לבצע כאשר רוצים לבצע הסבה מטיפוס כללי יותר (או מחלקת בסיס) לטיפוס ספציפי יותר (או מחלקה יורשת), מכיוון שבמקרה כזה קיימת הסכנה שהאובייקט לא יהייה מהטיפוס הנכון , אלא אולי מטיפוס מחלקה אחרת שירשה ממחלקת האב, וכמשנה זהירות אנו נדרשים להצהיר על כך במפורש (כלומר המהדר לא מוכן לקחת על עצמו אחריות במקרה כזה :) ). ההסבה ההפוכה היא בטוחה, מכיוון שכל אובייקט ממחלקה יורשת הוא גם אובייקט של מחלקת האב, והמהדר אינו דורש מאיתנו להצהיר על כך במפורש. בנוסף, הסבה בין טיפוסים בסיסיים שלא מתקיימים ביניהם יחסים של ירושה כמו int ו- long פועלת על עיקרון דומה, כאשר ניתן להסב מטיפוס שטופס פחות מקום בזיכרון (int במקרה הזה) לטיפוס שתופס יותר מקום (long) ב- Implicit Cast, מכיוון שאין חשש לאבד נתונים, בעוד שעל ההסבה ההפוכה אנו נדרשים להצהיר במפורש (Explicit Cast) , כי המספר שנשמר כ- long יכול שלא להיכנס בזיכרון העומד לרשות מספר מטיפוס int.

אנדי וואו! תודה על ההסבר המעמיק, פרופסור!
למעשה, אם אנחנו רוצים לדייק, המתודה setBackgroundColor שבה השתמשנו קיימת גם במחלקת האב – View, ולא היינו חייבים לבצע את ההסבה.
בחרנו לעשות זאת, לא רק כדי להציג לכם עקרון נוסף של הנדסת תוכנה, אלא גם כדי לאפשר לכם לחקור מאפיינים נוספים של ה- TextView השייכים רק למחלקה זו.
מקווים שתהנו :)

לבסוף, אנחנו מעבירים למתודה findViewByID את ה- ID של הרכיב הגראפי שלנו. כדי למצוא אותו, אנחנו משתמשים במחלקה R.
המזהה שלנו (ה- Android:Id) לרכיב ה- TextView הוא TextView01. שימו לב שאם תיכנסו לקובץ ה- XML של ה- Layout ותשנו אותו, אז גם פה הוא ישתנה.

שורה 7: כעת יש לנו משתנה בשם myTextView שמכיל את הרכיב הגראפי שלנו ונוכל לקרוא לפעולות שונות כדי לשנות אותו, דרך הקוד.
במקרה הזה קראנו למתודה setBackgroundColor כדי לשנות את צבע הרקע של ה- TextView שלנו.

התוצאה?

תוצאה של קריאה יזומה למתודה setBackgroundColor על TextView באנדרואיד

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

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

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

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