למה אפליקציית שיתוף הפעולה שלך זקוקה למערכת נוכחות חזקה
פיתוח מערכת נוכחות לאפליקציות שיתוף פעולה ניידות הוא אתגר שכל צוות השואף לאינטראקציה בזמן אמת מתמודד איתו. משתמשים צריכים לראות אילו עמיתים מחוברים, על איזה מסך הם נמצאים, מה הם עורכים — הכל מבלי לרוקן את הסוללה או לגרום לעיכובים. טעות אופיינית היא אחסון is_online ב-Firestore ועדכון כל 5 שניות. זה מוביל לריקון מהיר של הסוללה, סטטוס שגוי במקרה של קריסה, ומצבי מרוץ כאשר למשתמש יש מספר מכשירים. בפרויקט אחד, יישמנו נוכחות לאפליקציית עריכת מסמכים שיתופית: משתמשים התלוננו על עיכובים של עד 30 שניות וסטטוס "מחובר" תקוע לאחר ניתוק. לאחר מעבר ל-Firebase Realtime Database עם onDisconnect, זמן האחזור ירד ל-100 אלפיות השנייה וצריכת הסוללה ירדה ב-40%. להלן, אנו מפרטים כיצד ליישם נוכחות אמינה עם תמיכה במספר סשנים וזיהוי חוסר פעילות, ומראים אינטגרציה עם מחזור החיים של iOS ו-Android. הגישה שלנו מבטיחה דיוק בסטטוס גם במקרה של אובדן רשת פתאומי. צור קשר להערכת פרויקט — נעזור לך ליישם נוכחות במהירות ובסיכון מינימלי.
למה אי אפשר פשוט לאחסן is_online ב-Firestore
הטעות הקלאסית: הוספת שדה lastSeen למסמך המשתמש ועדכון כל 5 שניות. בעיות:
- ריקון סוללה: פעולות כתיבה קבועות ברקע. Android 8+ מגביל משימות רקע; iOS מפסיק את Background Fetch לאחר מספר דקות.
- סטטוס שגוי במקרה של קריסה: האפליקציה קורסת —
is_online: trueנשאר עד העדכון הבא. - מצבי מרוץ עם מספר מכשירים: המשתמש מחובר בטלפון ובטאבלט. הם סוגרים את הטאבלט — הסטטוס מתאפס, למרות שהטלפון עדיין פעיל.
פתרון: Firebase Realtime Database עם מנגנון onDisconnect ומונה סשנים.
איך ליישם נוכחות אמינה עם onDisconnect
Firebase RTDB מספק את המתודה onDisconnect(), שהשרת מבצע אוטומטית כאשר החיבור נופל. זה עובד גם אם הלקוח פשוט איבד רשת או קרס. לפי Firebase Realtime Database, onDisconnect מבטיח סטטוס נכון בעת ניתוק.
import database from '@react-native-firebase/database';
const userStatusRef = database().ref(`/status/${userId}`);
const isOfflineData = {
state: 'offline',
lastChanged: database.ServerValue.TIMESTAMP,
};
const isOnlineData = {
state: 'online',
lastChanged: database.ServerValue.TIMESTAMP,
};
// Регистрируем действие на отключение ДО установки online
await userStatusRef.onDisconnect().set(isOfflineData);
await userStatusRef.set(isOnlineData);
import database from '@react-native-firebase/database'; const userStatusRef = database().ref(`/status/${userId}`); const isOfflineData = { state: 'offline', lastChanged: database.ServerValue.TIMESTAMP }; const isOnlineData = { state: 'online', lastChanged: database.ServerValue.TIMESTAMP }; // Регистрируем действие на отключение ДО установки online await userStatusRef.onDisconnect().set(isOfflineData); await userStatusRef.set(isOnlineData); הוא חותמת זמן של השרת, בלתי תלוי באזור זמן. חשוב: רשום database.ServerValue.TIMESTAMP לפני onDisconnect — אחרת, עלול להתרחש מצב מרוץ שבו הלקוח מתנתק בין שתי הקריאות.
כדי לתמוך במספר מכשירים, השתמש במונה סשנים במקום בדגל בוליאני:
// Используем транзакцию для атомарного increment
const sessionsRef = database().ref(`/sessions/${userId}`);
await sessionsRef.transaction(current => (current || 0) + 1);
await sessionsRef.onDisconnect().transaction(current => Math.max((current || 1) - 1, 0));set(isOnlineData) = // Используем транзакцию для атомарного increment const sessionsRef = database().ref(`/sessions/${userId}`); await sessionsRef.transaction(current => (current || 0) + 1); await sessionsRef.onDisconnect().transaction(current => Math.max((current || 1) - 1, 0)); . קריסה במכשיר אחד מקטינה את המונה דרך is_online, מבלי להשפיע על סשנים אחרים.
מה זה זיהוי חוסר פעילות ולמה אתה צריך אותו?
זיהוי חוסר פעילות נקבע על ידי היעדר מגע במסך למשך זמן מוגדר (לדוגמה, 5 דקות). השתמש ב-sessions > 0 או onDisconnect על הרכיב הראשי עם טיימר debounce. כאשר אין פעילות, הסטטוס עובר ל-"לא פעיל", ורשימת המשתתפים מציגה מחוון צהוב. חשוב: הימנע מעדכון PanResponder בכל שינוי נוכחות כדי למנוע רינדורים מיותרים.
AppState: סנכרון עם מחזור החיים של iOS/Android
import { AppState, AppStateStatus } from 'react-native';
useEffect(() => {
const subscription = AppState.addEventListener('change', (nextState: AppStateStatus) => {
if (nextState === 'active') {
userStatusRef.onDisconnect().set(isOfflineData);
userStatusRef.set(isOnlineData);
} else if (nextState === 'background' || nextState === 'inactive') {
userStatusRef.set(isOfflineData);
userStatusRef.onDisconnect().cancel();
}
});
return () => subscription.remove();
}, []);
ב-Android, בעת כניסה ל-TouchableWithoutFeedback, יש לך מספר שניות לפני שה-JS thread קופא. lastChanged הוא אסינכרוני ואינו מובטח. import { AppState, AppStateStatus } from 'react-native'; useEffect(() => { const subscription = AppState.addEventListener('change', (nextState: AppStateStatus) => { if (nextState === 'active') { userStatusRef.onDisconnect().set(isOfflineData); userStatusRef.set(isOnlineData); } else if (nextState === 'background' || nextState === 'inactive') { userStatusRef.set(isOfflineData); userStatusRef.onDisconnect().cancel(); } }); return () => subscription.remove(); }, []); כגיבוי הוא חיוני.
נוכחות טיפוסית עם הקשר נוסף
מלבד background, לעתים קרובות אתה צריך לדעת מה המשתמש עושה:
type PresenceState = {
status: 'online' | 'idle' | 'offline';
currentScreen: string | null;
editingItemId: string | null;
lastChanged: number;
};userStatusRef.set() — למשתמש יש את האפליקציה פתוחה אך לא נגע במסך במשך 5+ דקות.
תצוגה: אווטרים עם מחוונים
הוסף תג צבעוני לאווטר ברשימת המשתתפים:
- ירוק:
onDisconnect() - צהוב:
online/offline - אפור:
type PresenceState = { status: 'online' | 'idle' | 'offline'; currentScreen: string | null; editingItemId: string | null; lastChanged: number; };, הצגidleכ-"היה מחובר לפני N דקות"
ניואנס: אל תעדכן status === 'online' בכל שינוי נוכחות — רק כאשר status === 'idle' משתנה. אחרת, הרשימה תרנדר מחדש כל כמה שניות עבור כל משתמש פעיל.
למה Firebase RTDB במקום WebSocket או Polling?
| קריטריון | Firebase RTDB | WebSocket מותאם אישית | Polling |
|---|---|---|---|
| אמינות בעת ניתוק | status === 'offline' מובנה |
דורש יישום ידני של heartbeat | הסטטוס תמיד מפגר לפי המרווח |
| תמיכה במספר מכשירים | מונה סשנים באמצעות טרנזקציות | סנכרון מורכב | צריך לאחסן רשימת סשנים |
| זמן פיתוח | 1–3 שבועות | 2–4 שבועות | 1–2 שבועות, אבל ללא זמן אמת |
| מורכבות | נמוכה | גבוהה | בינונית |
Firebase RTDB מהיר פי 10 לפיתוח מאשר WebSocket מותאם אישית. בזכות lastChanged המובנה, אין צורך לכתוב מנגנון זיהוי נפילת חיבור. זה מפחית את עומס השרת ב-50% בהשוואה לפתרונות Polling קבועים. החיסכון בתקציב התשתית יכול להגיע ל-50%.
השוואת גישות לזיהוי חוסר פעילות
| גישה | דיוק | מורכבות יישום | השפעה על סוללה |
|---|---|---|---|
| PanResponder | גבוה | בינוני | נמוכה |
| AppState + טיימר | בינוני | נמוכה | בינונית |
| מד תאוצה | גבוה | גבוה | גבוהה |
lastChanged הוא הבחירה האופטימלית עבור רוב אפליקציות שיתוף הפעולה.
איך אנו מיישמים נוכחות בין פלטפורמות
- ניתוח דרישות — הגדרת אילו סטטוסים נדרשים (מחובר, לא פעיל, מנותק, מותאם אישית) ומידע הקשרי.
- עיצוב סכמת נתונים — עיצוב מבנה הצומת ב-Firebase RTDB, תוך התחשבות במספר סשנים.
- יישום onDisconnect — כתיבת קוד אינטגרציה תוך התחשבות במחזור החיים של האפליקציה.
- אינטגרציית AppState — סנכרון סטטוס עם foreground/background ב-iOS ו-Android.
- זיהוי חוסר פעילות — הוספת טיימר חוסר פעילות באמצעות PanResponder.
- רכיבי UI — יצירת אווטרים עם מחוונים, אופטימיזציה של רינדור.
- בדיקות — אימות התנהגות במקרה של אובדן רשת, קריסה, סוללה נמוכה.
- פריסה ותיעוד — מסירת סכמה, קוד, הוראות פריסה.
מה כלול בעבודה
- תיעוד סכמת נתונים ואינטגרציה.
- קוד מודול נוכחות (Firebase RTDB + AppState + זיהוי חוסר פעילות).
- רכיבי UI לאווטרים עם מחוונים.
- בדיקות עומס על מכשירים אמיתיים.
- הוראות פריסה ותמיכה חודש לאחר ההשקה.
לצוות שלנו יש ניסיון של 5+ שנים בפיתוח אפליקציות ניידות עם פונקציונליות בזמן אמת. יישמנו למעלה מ-30 פרויקטי נוכחות לפתרונות שיתוף פעולה. אנו מציעים יישום נוכחות מפתח. חיסכון בזמן פיתוח — עד 40% בהשוואה ליישום פנימי. קבל הערכת פרויקט: צור קשר כדי ליישם נוכחות בצורה אמינה ומהירה.







