חזרה ל־016: חיבור המשחק ל־SignalR
מדריך זה הוא שלב הכנה בלבד. המטרה: ליצור עותק של משחק ה-TicTacToe, להשאיר את הגרסה עם SignalR כמו שהיא, ולהכין מסך חדש ונקי לקראת עבודה עם Firebase RTDB.
במילים פשוטות:
MainActivityנשאר המסך של SignalR.Main2Activityיהיה המסך החדש שעליו נבנה RTDB בהמשך.
למה משכפלים כאן, אף שכפילות בדרך כלל אינה רצויה?
זהו פיצול לימודי מכוון: MainActivity נשארת דוגמה עובדת של SignalR, ו־Main2Activity
נעשית נקודת התחלה ל־RTDB. כך אפשר להשוות שתי טכנולוגיות זמן־אמת באותו פרויקט בלי לפרק
תוצאה שכבר עובדת.
המחיר הוא שכפילות זמנית של קוד הלוח. במוצר ארוך־חיים היינו שוקלים לחלץ את המשותף ל־View,
Fragment או controller משותף. בשלב הזה חילוץ כזה יוסיף הפשטה לפני שהתלמיד פגש את שני
המקרים, ולכן שומרים את TicTacToeModel כמשותף ומפרידים רק את מסכי התקשורת.
וידאו מלווה + נקודות זמן
הסרטון המלווה לשלב הזה: YouTube
- פתיח ומטרת ההכנה: 00:01
- שכפול
MainActivityב-UI: 01:26 - הוספה ל-Manifest: 01:57
- למה עושים Commit ביניים לפני תפריט: 03:02
- חיבור ל-Drawer דרך
MenuActivity: 04:03 - זיהוי השלב החסר ב-
menu_drawer.xml: 05:18 - ניקוי SignalR בעזרת diff מבוקר: 09:45
- סיום ו-Commit/Push: 12:15
אינדיקציות ביצועים מהסרטון: פתיחת האפליקציה כשהאמולטור כבר רץ היא בערך 3-4 שניות (00:23, 07:08); מוצג גם הקשר חומרה בסיסי (Ryzen 5, SSD מהיר, 32GB RAM) (00:37, 01:04).
שלב 1 - שכפול MainActivity ל-Main2Activity
השכפול נעשה דרך ה-UI של Android Studio (לא ידנית דרך Explorer):
- בתצוגת
Project, עמדו עלMainActivity.java. - בצעו
CopyואזPasteבאותה תיקיה (activities). - תנו שם חדש:
Main2Activity. - ודאו שגם שם הקלאס בקובץ השתנה ל-
Main2Activity.
ראו הדגמה בסרטון: Copy/Paste + rename.
אם Android Studio לא שינה אוטומטית את שם הקלאס בתוך הקובץ, תקנו ידנית כדי ששם הקובץ ושם המחלקה יתאימו בדיוק.
הרגלי עבודה
הריצו Build + Run כבר עכשיו.
ראו בסרטון את הדגש על הרצה תכופה: 01:44.
שלב 2 - הוספה ל-Manifest
כעת נוסיף גם את ה-Activity החדש ל-AndroidManifest.xml.
app/src/main/AndroidManifest.xml
<application
...>
<activity
+ android:name=".activities.Main2Activity"
+ android:exported="false" />
+
<activity
android:name=".activities.MainActivity"
android:exported="false" />
</application>ראו בסרטון את ההוספה בפועל: 01:57.
אם אצלכם ה-package שונה או שהמחלקות לא יושבות בתיקיית activities, התאימו את הנתיב.
בדיקה + Git
Build + Run- ודאו שאין שגיאות Manifest.
- בצעו
Commit, Push(גם אם יש warnings לא קריטיים).
שלב 3 - הוספת Main2Activity לתפריט המגירה (Drawer)
המטרה עכשיו: מהתפריט נוכל להפעיל גם MainActivity וגם Main2Activity.
3.1 עדכון menu_drawer.xml
app/src/main/res/menu/menu_drawer.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/nav_home"
android:title="@string/menu_home" />
<item
android:id="@+id/nav_local_game"
android:title="@string/menu_local_game" />
+ <item
+ android:id="@+id/nav_rtdb_prep"
+ android:title="@string/menu_rtdb_prep" />
+
<item
android:id="@+id/nav_profile"
android:title="@string/menu_profile" />
</menu>זהו שלב שקל לפספס. אם ב-MenuActivity מופיע אדום על R.id.nav_rtdb_prep, כמעט תמיד חסר <item> בקובץ התפריט. בסרטון רואים בדיוק את התקלה הזו ואת הפתרון הידני: 05:18, 06:00.
בחלק מהפרויקטים הקובץ נקרא drawer_menu.xml ובחלק menu_drawer.xml. חשוב לערוך את הקובץ שבפועל מחובר ל-NavigationView דרך app:menu="...".
3.2 עדכון strings.xml
app/src/main/res/values/strings.xml
<resources>
...
<string name="menu_local_game">Local Game</string>
+ <string name="menu_rtdb_prep">RTDB Game (Prep)</string>
<string name="menu_profile">Profile</string>
</resources>3.3 ניתוב הפריט החדש ב-MenuActivity
app/src/main/java/com/example/tictacmenu/shell/MenuActivity.java
import android.content.Intent;
...
+import com.example.tictacmenu.activities.Main2Activity;
navigationView.setNavigationItemSelectedListener(item -> {
if (item.getItemId() == R.id.nav_home) {
showFragment(new HomeFragment());
} else if (item.getItemId() == R.id.nav_local_game) {
startActivity(new Intent(this, MainActivity.class));
+ } else if (item.getItemId() == R.id.nav_rtdb_prep) {
+ startActivity(new Intent(this, Main2Activity.class));
} else if (item.getItemId() == R.id.nav_profile) {
showFragment(new ProfileFragment());
}
drawerLayout.closeDrawer(GravityCompat.START);
return true;
});הדגמה בסרטון לחיבור ה-else if ב-MenuActivity: 04:10.
בדיקה + Git
Build + Run- ודאו שבתפריט יש 2 מסכי משחק וששניהם נפתחים.
- בצעו
Commit, Push.
בנקודה הזו יש לכם דוגמה מתועדת ב-Git של “איך מוסיפים Activity חדש למערכת התפריט”.
שלב 4 - בדיקה האם שני המסכים משתמשים באותו XML
זו בדיקת ידע חשובה:
- פתחו מהתפריט את שני המסכים.
- אם שניהם נראים אותו דבר, זה הגיוני: בדרך כלל שניהם עושים
setContentView(R.layout.activity_main). - אם הם נראים אחרת, גם מצוין, פשוט תדעו למה (למשל layout אחר או שינוי שכבר נעשה).
אין צורך “לתקן בכוח” אם שניהם משתמשים באותו XML. זה תקין לגמרי לשלב הכנה.
שלב 5 - ניקוי SignalR מתוך Main2Activity (ידני, לפי היסטוריה)
כאן מתחילים להחזיר את Main2Activity למצב מוקדם יותר, לפני SignalR.
מה עושים
- פתחו את היסטוריית הגרסאות של
MainActivity. - מצאו גרסה מלפני מדריך 016 (SignalR), למשל סביב 015.
- העתיקו משם את הקוד של
MainActivity. - הדביקו אל
Main2Activity. - ודאו ששם המחלקה נשאר
Main2Activity.
דיוק חשוב - Copy/Paste מבוקר לפי diff
לא לבצע “הדבקה עיוורת”. עובדים כמו רגרסיה מבוקרת:
- מבצעים paste מהגרסה הישנה.
- פותחים את חלון ה-diff של הקובץ.
- משאירים רק שינויים שרלוונטיים להסרת SignalR.
- מתקנים מיד הבדלים טכניים צפויים (למשל שם מחלקה
Main2Activity, imports נכונים). - מריצים
Build + Runלפני שממשיכים.
ראו בסרטון: 09:45, 10:04, 10:35.
מה אמור להיעלם מהעותק החדש
Main2Activity לא אמור לכלול יותר קוד SignalR.
-import com.example.tictacmenu.services.SignalRService;
-import android.util.Log;
-import android.widget.EditText;
...
-private final SignalRService signalRService = new SignalRService();
...
-public void onConnectClick(View view) {
- // התחברות ל-hub
-}
...
-@Override
-public void onReceiveKey(String key) {
- // טיפול במהלך שהגיע מרשת
-}במקום זאת, Main2Activity צריך להיות מסך משחק לוקאלי ונקי שעליו נבנה RTDB בהמשך.
בדיקה בסיום
Build + Run- פתחו מהתפריט את
MainActivity(SignalR) וגם אתMain2Activity(הכנה ל-RTDB). - ודאו ששניהם נפתחים ושאין קריסה.
סיכום
יצרנו הפרדה טובה בין שני מסלולים:
- מסלול קיים: TicTacToe עם SignalR (
MainActivity) - מסלול חדש: TicTacToe נקי לקראת Firebase RTDB (
Main2Activity)
בשיעורים הבאים נבנה על Main2Activity תמיכה ב-Firebase RTDB, כולל (אולי):
- סנכרון מהלכים בזמן אמת
- יצירה/הצטרפות למשחק (multi games / join game)
- שימוש ביכולות push של RTDB לעדכון לקוחות
המשך
מורה־עזר ב־Gemini
פתחו את Gem: מורה דרך: מסכים ותפריט TicTacMenu כדי לקבל רמזים, שאלות אבחון והסברים המתאימים לשלב שבו אתם נמצאים.