Android PlacesClient未关闭引发垃圾回收错误问题求助
解决Google Maps Places Client退出Fragment时的ManagedChannel未关闭错误
问题重现
使用以下代码创建Places Client:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (!Places.isInitialized()) { Places.initialize(this.requireActivity(), BuildConfig.MAP_API_KEY) } placesClient = Places.createClient(requireActivity()) }
退出地图Fragment时抛出错误:
*\~*\~*\~ Previous channel {0} was garbage collected without being shut down! \~*\~*\~* Make sure to call shutdown()/shutdownNow() java.lang.RuntimeException: ManagedChannel allocation site at com.google.android.libraries.places.internal.zzbme.<init>(com.google.android.libraries.places:places@@3.5.0:3) at com.google.android.libraries.places.internal.zzbmf.<init>(com.google.android.libraries.places:places@@3.5.0:2) at com.google.android.libraries.places.internal.zzbmd.zza(com.google.android.libraries.places:places@@3.5.0:18) at com.google.android.libraries.places.internal.zzazt.zza(com.google.android.libraries.places:places@@3.5.0:1) at com.google.android.libraries.places.internal.zzjn.zza(com.google.android.libraries.places:places@@3.5.0:26) at com.google.android.libraries.places.api.Places.zza(com.google.android.libraries.places:places@@3.5.0:7) at com.google.android.libraries.places.api.Places.createClient(com.google.android.libraries.places:places@@3.5.0:3) at com.FragmentMapLocation.onCreate(FragmentChargerMapLocation.kt:71) at androidx.fragment.app.Fragment.performCreate(Fragment.java:3094) at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:504) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:268) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1943) ...
尝试在onStop置空placesClient、onDestroy调用close(),但错误依旧:
override fun onStop() { super.onStop() placesClient = null } override fun onDestroy() { super.onDestroy() // Shut down the PlacesClient try { (placesClient as? AutoCloseable)?.close() } catch (e: Exception) { e.printStackTrace() } }
解决方案
问题核心是调用close()前已经把placesClient置空,导致close()根本没有执行。调整逻辑顺序即可解决:
- 移除
onStop中的置空操作 - 在
onDestroy或onDestroyView中先执行close(),再置空对象
修改后的代码示例:
override fun onDestroy() { super.onDestroy() // 先关闭资源再置空对象 try { (placesClient as? AutoCloseable)?.close() } catch (e: Exception) { e.printStackTrace() } placesClient = null } // 移除onStop里的置空代码 override fun onStop() { super.onStop() }
如果Fragment存在复用场景(onDestroy不会立即触发),更推荐在onDestroyView中执行关闭操作:
override fun onDestroyView() { super.onDestroyView() try { (placesClient as? AutoCloseable)?.close() } catch (e: Exception) { e.printStackTrace() } placesClient = null }
原理说明
PlacesClient内部的ManagedChannel需要显式关闭才能释放底层资源,若先置空placesClient,后续的close()调用会因为对象为null被跳过,导致Channel未被正确关闭,触发垃圾回收时的报错。
内容的提问来源于stack exchange,提问作者Praveen
相关产品推荐
相关产品推荐

