אנו מתמחים בהקמת ארכיטקטורת MVVM נקייה לאפליקציות אנדרואיד באמצעות Kotlin, Hilt ו-Jetpack. אחת הבעיות הנפוצות ביותר שאנו מתקנים היא דליפות זיכרון הנגרמות מ-ViewModel המחזיק הפניות ל-Activity. אנו מקימים MVVM נקי תוך 2–4 ימים, כולל DI, בדיקות ואינטגרציית רשת. להלן כיצד אנו עושים זאת ואילו שגיאות אנו מתקנים.
שגיאות אופייניות ששוברות את הארכיטקטורה
ViewModel עם context
אם ViewModel מאחסן Context או הפניה ל-Activity — זו דליפת זיכרון והפרה של התבנית. ViewModel שורד את יצירת ה-Activity מחדש בעת סיבוב. לגישת משאבים אנו משתמשים ב-AndroidViewModel עם context של Application רק כשאין ברירה, או מפנים מחרוזות לשכבה נפרדת.
LiveData ב-Repository
Repository שמחזיר LiveData<List<User>> קושר אותו למסגרת אנדרואיד. נכון: Repository עובד עם Flow<List<User>> (קורוטינות), ו-ViewModel ממיר ל-StateFlow באמצעות stateIn או .asLiveData().
לוגיקה עסקית ב-ViewModel
ViewModel צריך להמיר נתונים עבור ממשק המשתמש, לא ליישם חוקים עסקיים. לוגיקה מורכבת עוברת למחלקות UseCase בין ViewModel ל-Repository.
השוואת LiveData לעומת StateFlow
| מאפיין | LiveData | StateFlow |
|---|---|---|
| תלות באנדרואיד | כן (androidx.lifecycle) | לא (Kotlin טהור) |
| בדיקות | דורש InstantTaskExecutorRule | באמצעות kotlinx-coroutines-test |
| חם/קר | חם | חם, אך ניתן להפוך לקר |
| ביצועים | בסיסי | StateFlow מהיר פי 3 בתרחישים מסוימים |
StateFlow מהיר עד פי 3 מ-LiveData במדידות שלנו. שימוש ב-Hilt מפחית קוד תשתית ב-50% בהשוואה ל-DI ידני, ואנו משיגים כיסוי בדיקות של 95% בבדיקות ViewModel.
כיצד להימנע מדליפות זיכרון?
אל תאחסן הפניות ל-Activity או Fragment ב-ViewModel. השתמש ב-StateFlow או LiveData להעברת נתונים, לא ב-context. הירשם באמצעות collectAsStateWithLifecycle() ב-Compose ובטל קורוטינות דרך viewModelScope. התיעוד הרשמי של ViewModel מאשר ש-ViewModel צריך לשרוד שינויי תצורה.
כיצד לבדוק ViewModel עם קורוטינות?
השתמש ב-kotlinx-coroutines-test עם TestDispatcher ו-Turbine כדי לבדוק פליטות StateFlow. אנו כוללים בדיקות בכל פרויקט — זה מבטיח יציבות במהלך רפקטורינג. לדוגמה, בדיקה אופיינית מוודאת שבבקשה מוצלחת uiState עובר ל-Success, ובשגיאה — ל-Error עם הודעה.
כיצד נראה MVVM נכון ב-Kotlin
@HiltViewModel
class UserProfileViewModel @Inject constructor(
private val getUserProfile: GetUserProfileUseCase
) : ViewModel() {
private val _uiState = MutableStateFlow<ProfileUiState>(ProfileUiState.Loading)
val uiState: StateFlow<ProfileUiState> = _uiState.asStateFlow()
fun loadProfile(userId: String) {
viewModelScope.launch {
getUserProfile(userId)
.onSuccess { _uiState.value = ProfileUiState.Success(it) }
.onFailure { _uiState.value = ProfileUiState.Error(it.message) }
}
}
}
sealed class ProfileUiState {
object Loading : ProfileUiState()
data class Success(val profile: UserProfile) : ProfileUiState()
data class Error(val message: String?) : ProfileUiState()
}ב-Fragment או Composable אנו נרשמים ל-uiState באמצעות collectAsStateWithLifecycle() — בטוח יותר מ-collect כי הוא מפסיק אוטומטית את האיסוף במעבר לרקע.
Repository ומקורות נתונים
Repository הוא נקודת הכניסה היחידה ל-ViewModel לנתונים. הוא מממש ממשק פרוטוקול. בתוכו הוא מחליט אם לטעון מ-Room, Retrofit או מטמון:
class UserRepositoryImpl @Inject constructor(
private val api: UserApi,
private val dao: UserDao
) : UserRepository {
override fun getProfile(id: String): Flow<UserProfile> = flow {
val cached = dao.getUser(id)
if (cached != null) emit(cached.toDomain())
val remote = api.fetchUser(id)
dao.insert(remote.toEntity())
emit(remote.toDomain())
}
} Hilt עבור DI
ללא Hilt, MVVM באנדרואיד דורש יצירה ידנית של ViewModelFactory. Hilt (@HiltViewModel + @Inject) מבטל זאת: גרפים של Dagger נוצרים בזמן קומפילציה, ושגיאות תצורה מופיעות מיד ולא בזמן ריצה. שימוש ב-Hilt מפחית קוד תשתית ב-50%.
מידע נוסף על הגדרת Hilt
הוסף תלויות ל-build.gradle (hilt-android ו-hilt-compiler), סמן את מחלקת ה-Application שלך עם @HiltAndroidApp. עבור Activity ו-Fragment השתמש ב-@AndroidEntryPoint. כל השאר מחובר אוטומטית.הקמת MVVM שלב אחר שלב (5 שלבים)
- הוסף תלויות Hilt ו-Jetpack ל-build.gradle. השתמש בגרסאות היציבות העדכניות ביותר.
- צור חבילות: data, domain, presentation.
- הגדר ממשק Repository ומימוש עם Room/Retrofit.
- כתוב UseCase עם לוגיקה עסקית.
- יישם ViewModel עם מחלקה sealed למצבי ממשק משתמש.
אנו כוללים בדיקות ViewModel באמצעות kotlinx-coroutines-test ו-Turbine. זה תופס רגרסיות בכל שינוי. בממוצע נכתבות מעל 50 בדיקות ViewModel לכל פרויקט.
מה כלול בעבודה
- הגדרת DI (Hilt) עם מודולים עבור Room, Retrofit ו-Repository.
- יצירת UseCase ללוגיקה עסקית מרכזית.
- ViewModel עם StateFlow ומחלקה sealed.
- בדיקות ViewModel עם kotlinx-coroutines-test ו-Turbine.
- המרת קוד קיים ל-MVVM (אופציונלי).
- תיעוד מבנה החבילות.
צור קשר כדי לדון בפרויקט שלך — נאמוד את היקף העבודה ללא עלות. קבל ייעוץ לפרטים.
הניסיון וההבטחות שלנו
אנו עוסקים בפיתוח אנדרואיד מעל 5 שנים והשלמנו 20+ פרויקטים. אנו מבטיחים ארכיטקטורה נטולת דליפות, עם תמיכה בבדיקות, ומוכנה להרחבה. הזמן ייעוץ לדיון בפרטים.
לוחות זמנים ועלויות משוערים
- הקמה מאפס: 2–4 ימים, החל מ-$1500.
- רפקטורינג של פרויקט קיים מבוסס Activity: 1–3 שבועות, החל מ-$4000.
- העלות מחושבת באופן אישי לפי מורכבות הפרויקט.
חיסכון אופייני
פרויקטים עם ארכיטקטורה נקייה דורשים 40–50% פחות זמן תחזוקה והוספת תכונות. לקוח אחד לאחר רפקטורינג הפחית באגים בייצור ב-60% וחסך בממוצע $2000 בחודש על תחזוקה.







