3.8 KiB
3.8 KiB
✅ FIX: History Screen Close App - Root Cause & Solutions
🔍 Root Causes Identified
Issue 1: Race Condition dalam LaunchedEffect
Problem:
LaunchedEffect(Unit) {
userPreferences.npmFlow.collect { npm ->
currentNpm = npm
}
}
LaunchedEffect(Unit) {
userPreferences.namaFlow.collect { nama ->
currentNama = nama
}
}
- Dua LaunchedEffect dengan key yang sama (Unit) bersaing satu sama lain
- Bisa menyebabkan currentNpm tidak ter-load dengan benar saat membuka history
- Akibat:
currentNpmmasih null saat navigasi ke history → crash
Issue 2: No Error Handling di Composable History
Problem:
composable("history") {
val attendanceList by repository.getAttendanceByNpm(
currentNpm ?: "" // Bisa null jika loading belum selesai
).collectAsState(initial = emptyList())
HistoryScreen(attendanceList = attendanceList, ...)
}
currentNpmbisa null jika Flow belum selesai di-loadcollectAsStatebisa throw exception- Tidak ada error handling → langsung crash
✅ Solutions Applied
Solution 1: Added Error Handling di LaunchedEffect
LaunchedEffect(Unit) {
try {
userPreferences.npmFlow.collect { npm ->
currentNpm = npm
isUserLoaded = npm != null // Track loading state
}
} catch (e: Exception) {
currentNpm = null
isUserLoaded = false
}
}
Solution 2: Improved History Composable dengan Try-Catch & Null Safety
composable("history") {
try {
val npmForHistory = currentNpm ?: ""
if (npmForHistory.isEmpty()) {
// Show user-friendly warning
Box(modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center) {
Text("NPM tidak ditemukan. Silakan login ulang.")
}
} else {
val attendanceList by repository.getAttendanceByNpm(npmForHistory)
.collectAsState(initial = emptyList())
HistoryScreen(
attendanceList = attendanceList,
onBackClick = { navController.navigateUp() }
)
}
} catch (e: Exception) {
// Fallback error UI
Box(modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center) {
Text("Error: ${e.message ?: "Tidak dapat membuka riwayat"}")
}
}
}
Solution 3: Added Required Imports
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
📊 Changes Summary
| Komponen | Sebelum | Sesudah |
|---|---|---|
| LaunchedEffect | ❌ No error handling | ✅ Try-catch + state tracking |
| History Composable | ❌ No null check | ✅ Defensive null check |
| Error Handling | ❌ None | ✅ Try-catch with fallback UI |
| Loading State | ❌ None | ✅ isUserLoaded flag |
| User Feedback | ❌ Crash | ✅ Clear error messages |
🧪 Test Scenarios
✅ Test 1: Normal Flow
1. Login dengan npm valid
2. Tunggu loading selesai
3. Buka History
✅ Expected: Riwayat ditampilkan dengan aman
✅ Test 2: Rapid Navigation
1. Login
2. Langsung ke history (sebelum loading selesai)
✅ Expected: Tampil "NPM tidak ditemukan..." atau loading
✅ Test 3: Data Error
1. Network issue saat load preferences
2. Buka History
✅ Expected: Tampil user-friendly error message
📝 Files Modified
MainActivity.kt- Added error handling & improved history composable
🚀 Expected Results
✅ App tidak lagi crash saat membuka History ✅ User mendapat informasi jelas jika ada error ✅ Graceful handling untuk berbagai edge cases ✅ Proper state management untuk user preferences