LeakCanary通过匿名实现locationlistener报告泄露的活动实例

del*_*san 9 android memory-leaks anonymous-inner-class leakcanary

在onDestroy中

locationManager.removeUpdates(locationListener);
locationListener = null;
Run Code Online (Sandbox Code Playgroud)

匿名实现

locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        if (locationManager != null) {
            locationListener = new LocationListener() {
                @Override
                public void onLocationChanged(Location location) {
                    if (chatId != null) {
                        double radius = 6378.137;
                        double oldLat = mLastLocation.getLatitude();
                        double oldLng = mLastLocation.getLongitude();
                        double newLat = location.getLatitude();
                        double newLng = location.getLongitude();
                        double dLat = Math.toRadians(newLat - oldLat);
                        double dLng = Math.toRadians(newLng - oldLng);
                        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
                                + Math.cos(Math.toRadians(oldLat))
                                * Math.cos(Math.toRadians(newLat)) * Math.sin(dLng / 2)
                                * Math.sin(dLng / 2);
                        double c = 2 * Math.asin(Math.sqrt(a));
                        double valueResult = radius * c;
                        double difInMeters = valueResult * 1000;

                        if (difInMeters > 2.0) {

                            pushLocation(location);

                        }
                    }
                }

                @Override
                public void onStatusChanged(String provider, int status, Bundle extras) {
                    Log.d(TAG, "onStatusChanged: " + status);
                    switch (status) {
                        case LocationProvider.AVAILABLE:
                            Log.d(TAG, "GPS.Available");
                            break;
                        case LocationProvider.OUT_OF_SERVICE:
                            Log.d(TAG, "GPS.OutOfService");
                            break;
                        case LocationProvider.TEMPORARILY_UNAVAILABLE:
                            Log.d(TAG, "GPS.TemporarilyUnavailable");
                            break;
                    }
                }

                @Override
                public void onProviderEnabled(String provider) {
                    Log.d(TAG, "onProviderEnabled: " + provider.toString());
                }

                @Override
                public void onProviderDisabled(String provider) {
                    Log.d(TAG, "onProviderdisabled: " + provider.toString());
                }
            };
Run Code Online (Sandbox Code Playgroud)

从中导入LocationManager和LocationListener

import android.location.LocationListener;
import android.location.LocationManager;
Run Code Online (Sandbox Code Playgroud)

我使用后退按钮保留Activity,所以我尝试覆盖onBackPressed,并从onBackPressed中的locationManager中删除更新,但我得到了相同的泄漏.

以下是带泄漏的Logcat

D/LeakCanary: In findmyfriends:1.0:1.
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: * findmyfriends.ScrollingMessengerActivity has leaked:
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: * GC ROOT android.location.LocationManager$ListenerTransport.mListener
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: * references findmyfriends.ScrollingMessengerActivity$6.this$0 (anonymous implementation of android.location.LocationListener)
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: * leaks findmyfriends.ScrollingMessengerActivity instance
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: * Retaining: 0.89 MB.
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: * Reference Key: bead30b1-667e-45b1-8ccd-86a97abbfe43
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: * Device: samsung samsung SAMSUNG-SM-G891A poseidonlteuc
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: * Android Version: 6.0.1 API: 23 LeakCanary: 1.4 6b04880
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: * Durations: watch=5025ms, gc=173ms, heap dump=2093ms, analysis=34462ms
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: * Details:
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: * Instance of android.location.LocationManager$ListenerTransport
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: |   static TYPE_STATUS_CHANGED = 2
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: |   static TYPE_PROVIDER_DISABLED = 4
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: |   static TYPE_PROVIDER_ENABLED = 3
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: |   static TYPE_LOCATION_CHANGED = 1
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: |   static $staticOverhead = byte[32]@331418625 (0x13c10c01)
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: |   mListener = ScrollingMessengerActivity$6@324639008 (0x13599920)
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: |   mListenerHandler = android.location.LocationManager$ListenerTransport$1@322816704 (0x133dcac0)
09-26 18:28:13.367 25892-26857/findmyfriends D/LeakCanary: |   this$0 = android.location.LocationManager@322815648 (0x133dc6a0)
Run Code Online (Sandbox Code Playgroud)

我以前在onOrientationChange期间发现了locationListener的内存泄漏,

我通过放置解决了它

if (childListener != null) {
        mChatRef.removeEventListener(childListener);
        childListener = null;
    }
Run Code Online (Sandbox Code Playgroud)

在onSaveInstanceState中.并使用locationListener的匿名实现运行初始化函数.

为什么不locationManager.removeUpdates(locationListener)发布对活动的引用?任何建议,将不胜感激!提前致谢!!

编辑 确定,仍然没有解决MemoryLeak,但我删除了匿名类,而是我有Activity实现LocationListener.

我仍然得到相同的内存泄漏.

小智 0

我相信你不需要使用onDestroy事件,而是使用onPause。当 Activity 被销毁时,您无需担心,因为侦听器将被杀死并从内存中删除,但当 Activity 进入后台时,将调用 onPause。

就我而言,问题是我没有从 onPause 中删除侦听器,因此它继续从 LocationManager 获取结果。