diff --git a/src/android/app/src/main/java/org/citron/citron_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/citron/citron_emu/fragments/EmulationFragment.kt index 5ea9d6d34..1c183cf22 100644 --- a/src/android/app/src/main/java/org/citron/citron_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/citron/citron_emu/fragments/EmulationFragment.kt @@ -526,11 +526,16 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { if (emulationViewModel.emulationStarted.value && !emulationViewModel.isEmulationStopping.value ) { - val perfStats = NativeLibrary.getPerfStats() - if (_binding != null) { + if (_binding != null && binding.fpsIndicatorView.isAttachedToWindow) { + val perfStats = NativeLibrary.getPerfStats() binding.fpsIndicatorView.updateFps(perfStats[FPS].toFloat()) + perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 800) + } + } else { + // Stop the updater if emulation is stopping + if (perfStatsUpdater != null) { + perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!) } - perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 800) } } perfStatsUpdateHandler.post(perfStatsUpdater!!) @@ -549,11 +554,16 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { if (emulationViewModel.emulationStarted.value && !emulationViewModel.isEmulationStopping.value ) { - if (_binding != null) { + if (_binding != null && binding.thermalIndicatorView.isAttachedToWindow) { val temperature = getBatteryTemperature(requireContext()) binding.thermalIndicatorView.updateTemperature(temperature) + thermalStatsUpdateHandler.postDelayed(thermalStatsUpdater!!, 2000) + } + } else { + // Stop the updater if emulation is stopping + if (thermalStatsUpdater != null) { + thermalStatsUpdateHandler.removeCallbacks(thermalStatsUpdater!!) } - thermalStatsUpdateHandler.postDelayed(thermalStatsUpdater!!, 2000) } } thermalStatsUpdateHandler.post(thermalStatsUpdater!!) @@ -572,10 +582,15 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { if (emulationViewModel.emulationStarted.value && !emulationViewModel.isEmulationStopping.value ) { - if (_binding != null) { + if (_binding != null && binding.ramMeterView.isAttachedToWindow) { binding.ramMeterView.updateRamUsage() + ramStatsUpdateHandler.postDelayed(ramStatsUpdater!!, 1500) + } + } else { + // Stop the updater if emulation is stopping + if (ramStatsUpdater != null) { + ramStatsUpdateHandler.removeCallbacks(ramStatsUpdater!!) } - ramStatsUpdateHandler.postDelayed(ramStatsUpdater!!, 1500) } } ramStatsUpdateHandler.post(ramStatsUpdater!!) @@ -1161,9 +1176,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { } companion object { - private val perfStatsUpdateHandler = Handler(Looper.myLooper()!!) - private val thermalStatsUpdateHandler = Handler(Looper.myLooper()!!) - private val ramStatsUpdateHandler = Handler(Looper.myLooper()!!) - private val shaderStatsUpdateHandler = Handler(Looper.myLooper()!!) + private val perfStatsUpdateHandler = Handler(Looper.getMainLooper()) + private val thermalStatsUpdateHandler = Handler(Looper.getMainLooper()) + private val ramStatsUpdateHandler = Handler(Looper.getMainLooper()) + private val shaderStatsUpdateHandler = Handler(Looper.getMainLooper()) } } diff --git a/src/android/app/src/main/java/org/citron/citron_emu/views/RamMeterView.kt b/src/android/app/src/main/java/org/citron/citron_emu/views/RamMeterView.kt index 2f234ee28..7fd81479f 100644 --- a/src/android/app/src/main/java/org/citron/citron_emu/views/RamMeterView.kt +++ b/src/android/app/src/main/java/org/citron/citron_emu/views/RamMeterView.kt @@ -35,7 +35,18 @@ class RamMeterView @JvmOverloads constructor( fun updateRamUsage() { try { - val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + // Safety check: ensure view is attached and has valid dimensions + if (!isAttachedToWindow || width <= 0 || height <= 0) { + Log.w("RamMeter", "View not ready for update (attached: $isAttachedToWindow, width: $width, height: $height)") + return + } + + val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as? ActivityManager + if (activityManager == null) { + Log.e("RamMeter", "ActivityManager service not available") + return + } + val memoryInfo = ActivityManager.MemoryInfo() activityManager.getMemoryInfo(memoryInfo) @@ -61,7 +72,6 @@ class RamMeterView @JvmOverloads constructor( ramUsagePercent = 0f usedRamMB = 0L totalRamMB = 0L - invalidate() } } @@ -92,16 +102,26 @@ class RamMeterView @JvmOverloads constructor( override fun onDraw(canvas: Canvas) { super.onDraw(canvas) - // Draw simple text-based RAM display - val usedGB = usedRamMB / 1024f - val totalGB = totalRamMB / 1024f - val ramText = if (totalGB >= 1.0f) { - "RAM: ${ramUsagePercent.roundToInt()}% (%.1fGB/%.1fGB)".format(usedGB, totalGB) - } else { - "RAM: ${ramUsagePercent.roundToInt()}% (${usedRamMB}MB/${totalRamMB}MB)" + // Safety check: ensure view has valid dimensions + if (width <= 0 || height <= 0) { + Log.w("RamMeter", "onDraw called with invalid dimensions (width: $width, height: $height)") + return } - canvas.drawText(ramText, 8f, height - 8f, textPaint) - Log.d("RamMeter", "onDraw called - RAM: $ramText") + try { + // Draw simple text-based RAM display + val usedGB = usedRamMB / 1024f + val totalGB = totalRamMB / 1024f + val ramText = if (totalGB >= 1.0f) { + "RAM: ${ramUsagePercent.roundToInt()}% (%.1fGB/%.1fGB)".format(usedGB, totalGB) + } else { + "RAM: ${ramUsagePercent.roundToInt()}% (${usedRamMB}MB/${totalRamMB}MB)" + } + canvas.drawText(ramText, 8f, height - 8f, textPaint) + + Log.d("RamMeter", "onDraw called - RAM: $ramText") + } catch (e: Exception) { + Log.e("RamMeter", "Error in onDraw", e) + } } } \ No newline at end of file