Android应用因内存占用过高崩溃:多次打开含API请求Activity异常
Hey there! Let's walk through why your app is crashing when you open that API-enabled Activity 3-4 times, and how to fix it.
First, let's break down the key clues from your logs:
Background sticky concurrent mark sweep GC freed 46562(2MB) AllocSpace objects, 0(0B) LOS objects, 15% free, 13MB/15MB, paused 7.087ms total 41.571ms
Skipped 241 frames! The application may be doing too much work on its main thread.
Skipped 356 frames! The application may be doing too much work on its main thread.
This tells us two critical issues:
- Memory pressure & leaks: Your app's heap is nearly full (13MB out of 15MB), so the garbage collector is working overtime but can't free up enough space. Repeatedly opening the Activity is likely leaving old instances stuck in memory (memory leaks) instead of being cleaned up.
- Main thread blocking: The "skipped frames" messages confirm heavy work (like API calls or data processing) is running directly on the main thread—this freezes the UI and worsens performance over time.
Common Causes & Practical Fixes
1. API Requests Running on the Main Thread
If you're making synchronous API calls directly in lifecycle methods like onCreate(), you're blocking the main thread (which is only meant for UI updates). This causes frame skips and slows down garbage collection.
Fix:
- Use asynchronous requests. For Retrofit, swap
execute()forenqueue():private var dataCall: Call<DataResponse>? = null fun fetchData() { dataCall = apiService.getData() dataCall?.enqueue(object : Callback<DataResponse> { override fun onResponse(call: Call<DataResponse>, response: Response<DataResponse>) { // Safely update UI here } override fun onFailure(call: Call<DataResponse>, t: Throwable) { // Handle error } }) } - For Kotlin Coroutines, launch requests in a background dispatcher:
lifecycleScope.launch(Dispatchers.IO) { val response = apiService.getData() withContext(Dispatchers.Main) { // Update UI with response data } }
2. Uncancelled Requests Causing Memory Leaks
When you close the Activity, ongoing API requests might hold a reference to the Activity (via callbacks or context), preventing it from being garbage collected. After 3-4 opens, these stuck instances fill up the heap and cause crashes.
Fix:
- Cancel all active requests in
onDestroy():override fun onDestroy() { super.onDestroy() // Cancel Retrofit call dataCall?.cancel() // For Coroutines using a custom Job: fetchJob?.cancel() } - Use
lifecycleScopefor Coroutines—it automatically cancels when the Activity is destroyed, so you don't have to manage jobs manually.
3. Hidden Memory Leaks
Even with cancelled requests, other references (like static variables, unregistered listeners, or anonymous inner classes) might keep old Activity instances alive.
Fix:
- Use Android Profiler's Memory tab: Take a heap dump after opening/closing the Activity a few times, then look for instances of your Activity that shouldn't exist—this points directly to a leak.
- Add LeakCanary to your debug build (it's lightweight and automatically alerts you to leaks, with details on what's holding the reference).
- Avoid using
thisin long-lived callbacks; useWeakReferenceinstead if you need to reference the Activity.
4. Heavy Data Processing on Main Thread
Parsing large JSON responses or processing data directly on the main thread also causes frame skips and slows down the app.
Fix:
- Move parsing/processing to a background thread:
lifecycleScope.launch(Dispatchers.IO) { val rawJson = apiService.getRawData() val parsedData = Gson().fromJson(rawJson, DataModel::class.java) withContext(Dispatchers.Main) { // Update UI with parsed data } } - For very large responses, use streaming parsers (like Moshi's
JsonReader) to avoid loading the entire JSON into memory at once.
Final Checks
After implementing these fixes, test by opening/closing the Activity multiple times and monitor:
- The Android Profiler Memory tab: Confirm old Activity instances are being garbage collected.
- Logcat: Verify no more "skipped frames" messages, and GC runs are less frequent.
内容的提问来源于stack exchange,提问作者Kishan Gupta

