com.google.android.gms.internal引起的内存泄漏。*

时间:2017-09-24 15:43:02

标签: android memory-leaks

我正在使用smart-location-lib获取设备的当前位置一次。它需要在活动的生命周期中稍后使用。

从活动中执行finish()返回上一个活动后,我发现内存泄漏。

以下是代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...

    SmartLocation.with(this).location()
    .oneFix()
    .start(new OnLocationUpdatedListener() {
        @Override
        public void onLocationUpdated(Location location) {
            mCurrentLocation = location;
        }
    });

    ...
}

...

@Override
protected void onStop() {
    super.onStop();

    SmartLocation.with(this).location().stop();
}

正如您所见,我正在活动的onStop()调用中执行smart-location-lib .stop(),如文档here中所述。

但这并不能防止泄漏。以下是LeakCanary收集的泄漏信息:

In com.companyname.appname.development:1.0-development:1.
* com.companyname.appname.activities.TaskCheckoutActivity has leaked:
* GC ROOT com.google.android.gms.internal.zzbyw.zzfwc
* references com.google.android.gms.internal.zzbyt.zzhyy
* references io.nlopez.smartlocation.location.providers.LocationGooglePlayServicesProvider.context
* leaks com.companyname.appname.activities.TaskCheckoutActivity instance

* Retaining: 1,6 MB.
* Reference Key: ba2a19b1-d5ca-4971-a5c7-e0fd99ea95a6
* Device: samsung samsung SM-G930F heroltexx
* Android Version: 7.0 API: 24 LeakCanary: 1.5.4 74837f0
* Durations: watch=5010ms, gc=215ms, heap dump=1792ms, analysis=128865ms

* Details:
* Instance of com.google.android.gms.internal.zzbyw
|   static $classOverhead = byte[752]@858164225 (0x33268c01)
|   zzfwc = com.google.android.gms.internal.zzbyt@861919192 (0x335fd7d8)
|   mDescriptor = java.lang.String@854648480 (0x32f0e6a0)
|   mObject = 501026202704
|   mOwner = com.google.android.gms.internal.zzbyw@856066112 (0x33068840)
|   shadow$_klass_ = com.google.android.gms.internal.zzbyw
|   shadow$_monitor_ = 0
* Instance of com.google.android.gms.internal.zzbyt
|   static $classOverhead = byte[792]@855184385 (0x32f91401)
|   zzhyy = io.nlopez.smartlocation.location.providers.LocationGooglePlayServicesProvider@856875576 (0x3312e238)
|   zzfda = com.google.android.gms.common.api.Api@856792448 (0x33119d80)
|   zzfip = com.google.android.gms.common.api.Api$zzf@854593816 (0x32f01118)
|   mStatus = com.google.android.gms.common.api.Status@856929688 (0x3313b598)
|   zzaj = true
|   zzaop = java.util.concurrent.CountDownLatch@855708832 (0x330114a0)
|   zzfhl = com.google.android.gms.common.api.Status@856929688 (0x3313b598)
|   zzfiz = java.lang.Object@854593632 (0x32f01060)
|   zzfja = com.google.android.gms.common.api.internal.zzu@856066144 (0x33068860)
|   zzfjb = java.lang.ref.WeakReference@857866976 (0x332202e0)
|   zzfjc = java.util.ArrayList@857867120 (0x33220370)
|   zzfjd = null
|   zzfje = java.util.concurrent.atomic.AtomicReference@855708848 (0x330114b0)
|   zzfjf = null
|   zzfjg = false
|   zzfjh = false
|   zzfji = null
|   zzfjj = null
|   zzfjk = false
|   shadow$_klass_ = com.google.android.gms.internal.zzbyt
|   shadow$_monitor_ = -1953408656
* Instance of io.nlopez.smartlocation.location.providers.LocationGooglePlayServicesProvider
|   static REQUEST_CHECK_SETTINGS = 20001
|   static GMS_ID = java.lang.String@856784656 (0x33117f10)
|   static $classOverhead = byte[748]@857097217 (0x33164401)
|   static REQUEST_START_LOCATION_FIX = 10001
|   alwaysShow = true
|   checkLocationSettings = false
|   client = com.google.android.gms.common.api.internal.zzbd@856996208 (0x3314b970)
|   context = com.companyname.appname.activities.TaskCheckoutActivity@860313600 (0x33475800)
|   fulfilledCheckLocationSettings = false
|   googlePlayServicesListener = io.nlopez.smartlocation.location.providers.LocationGooglePlayServicesWithFallbackProvider@856791392 (0x33119960)
|   listener = com.companyname.appname.activities.TaskCheckoutActivity$1@856799680 (0x3311b9c0)
|   locationRequest = com.google.android.gms.location.LocationRequest@856876304 (0x3312e510)
|   locationStore = io.nlopez.smartlocation.location.LocationStore@859517520 (0x333b3250)
|   logger = io.nlopez.smartlocation.utils.LoggerFactory$Sssht@854569160 (0x32efb0c8)
|   serviceListener = null
|   settingsResultCallback = io.nlopez.smartlocation.location.providers.LocationGooglePlayServicesProvider$1@856798672 (0x3311b5d0)
|   shouldStart = false
|   stopped = true
|   shadow$_klass_ = io.nlopez.smartlocation.location.providers.LocationGooglePlayServicesProvider
|   shadow$_monitor_ = -2147272239
* Instance of com.companyname.appname.activities.TaskCheckoutActivity
|   static $classOverhead = byte[4720]@856289281 (0x3309f001)
|   BARCODE_SCANNER_REQUEST = java.lang.Integer@856384016 (0x330b6210)
|   BEGIN_SIGNATURE_REQUEST = java.lang.Integer@856384000 (0x330b6200)
|   mApiKey = java.lang.String@856965696 (0x33144240)
|   mCheckoutEmptyStepView = null
|   mCurrentLocation = android.location.Location@859607248 (0x333c90d0)
|   mDamagedAddressUnknownDescriptionCheckFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mDamagedAddressUnknownDescriptionEditText = null
|   mDamagedAddressUnknownStepView = null
|   mJobManager = com.birbit.android.jobqueue.JobManager@851730080 (0x32c45ea0)
|   mKibCardInputCheckFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mKibCardInputEditText = null
|   mKibCardInputStepView = null
|   mKibCardNextTimeframe = null
|   mKibNextAbbrevation = null
|   mKibNextDay = null
|   mMarginBetweenStatusAndIcons = android.support.v7.widget.AppCompatTextView@860264448 (0x33469800)
|   mNameCheckFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mNeighbourAddressStepView = null
|   mNeighbourCityFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mNeighbourCityInputEditText = null
|   mNeighbourStreetFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mNeighbourStreetInputEditText = null
|   mNeighbourStreetNumberFailed = java.lang.Boolean@1881937152 (0x702c1500)
|   mNeighbourStreetNumberInputEditText = null
|   mNeighbourZipcodeFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mNeighbourZipcodeInputEditText = null
|   mOpenBarcodeScannerButton = null
|   mParcelKey = java.lang.String@856985856 (0x33149100)
|   mPaymentCompleted = java.lang.Boolean@1881937168 (0x702c1510)
|   mPaymentStepView = null
|   mPaymentSwitch = null
|   mPaymentTextView = null
|   mRecipientContainer = android.widget.RelativeLayout@860361728 (0x33481400)
|   mRecipientNameEditText = android.widget.EditText@860366848 (0x33482800)
|   mRefusedReasonCheckFailed = java.lang.Boolean@1881937168 (0x702c1510)
|   mRefusedReasonEditText = null
|   mRefusedStepView = null
|   mSignatureBitmap = android.graphics.Bitmap@854106464 (0x32e8a160)
|   mSignatureButton = android.widget.Button@860369920 (0x33483400)
|   mSignatureFragmentContainer = android.widget.RelativeLayout@860368896 (0x33483000)
|   mSignaturePreviewImageView = android.widget.ImageView@860370944 (0x33483800)
|   mSignatureStepView = android.widget.RelativeLayout@860360704 (0x33481000)
|   mSigned = java.lang.Boolean@1881937152 (0x702c1500)
|   mSpecialContainerTaskStatusTextView = android.support.v7.widget.AppCompatTextView@860262400 (0x33469000)
|   mSpecialIconA = android.support.v7.widget.AppCompatImageView@860296192 (0x33471400)
|   mSpecialIconB = android.support.v7.widget.AppCompatImageView@860297216 (0x33471800)
|   mSpecialIconC = android.support.v7.widget.AppCompatImageView@860298240 (0x33471c00)
|   mSpecialIconD = android.support.v7.widget.AppCompatImageView@860299264 (0x33472000)
|   mSpecialIconsLinearLayout = android.widget.LinearLayout@860261376 (0x33468c00)
|   mSteps = java.lang.String[2]@860283592 (0x3346e2c8)
|   mTask = com.companyname.appname.models..Task@857797632 (0x3320f400)
|   mTaskCheckout = com.companyname.appname.helpers.TaskCheckout@859397192 (0x33395c48)
|   mTaskCheckoutMainLinLayout = android.widget.LinearLayout@856667136 (0x330fb400)
|   mTaskStatus = com.companyname.appname.enums.TaskStatus@851451392 (0x32c01e00)
|   mTaskStatusLabel = android.widget.TextView@860358656 (0x33480800)
|   mTaskStatusSelectedIndex = java.lang.Integer@1882345520 (0x70325030)
|   mTaskStatusText = java.lang.String@858039008 (0x3324a2e0)
|   mTaskStatusTextView = android.widget.TextView@860359680 (0x33480c00)
|   mTaskStatusView = android.widget.FrameLayout@860321792 (0x33477800)
|   mVerticalStepperForm = ernestoyaquello.com.verticalstepperform.VerticalStepperFormLayout@860300288 (0x33472400)
|   mDelegate = android.support.v7.app.AppCompatDelegateImplN@856322976 (0x330a73a0)
|   mResources = null
|   mThemeId = 2131427510
|   mCreated = true
|   mFragments = android.support.v4.app.FragmentController@856383984 (0x330b61f0)
|   mHandler = android.support.v4.app.FragmentActivity$1@856395936 (0x330b90a0)
|   mNextCandidateRequestIndex = 0
|   mPendingFragmentActivityResults = android.support.v4.util.SparseArrayCompat@856400656 (0x330ba310)
|   mReallyStopped = true
|   mRequestedPermissionsFromFragment = false
|   mResumed = false
|   mRetaining = false
|   mStopped = true
|   mStartedActivityFromFragment = false
|   mStartedIntentSenderFromFragment = false
|   mExtraDataMap = android.support.v4.util.SimpleArrayMap@856309016 (0x330a3d18)
|   mActionBar = null
|   mActionModeTypeStarting = 0
|   mActivityInfo = android.content.pm.ActivityInfo@855609200 (0x32ff8f70)
|   mActivityTransitionState = android.app.ActivityTransitionState@856227168 (0x3308fd60)
|   mAppLockCheckRunnable = android.app.Activity$1@856383936 (0x330b61c0)
|   mAppLockIsInMultiWindowMode = false
|   mApplication = com.companyname.appname.DeliveryApplication@851900944 (0x32c6fa10)
|   mCalled = true
|   mChangeCanvasToTranslucent = false
|   mChangingConfigurations = false
|   mComponent = android.content.ComponentName@856313936 (0x330a5050)
|   mConfigChangeFlags = 0
|   mCurrentConfig = android.content.res.Configuration@855650184 (0x33002f88)
|   mDecor = null
|   mDefaultKeyMode = 0
|   mDefaultKeySsb = null
|   mDestroyed = true
|   mDoReportFullyDrawn = false
|   mEatKeyUpEvent = false
|   mEmbeddedID = null
|   mEnableDefaultActionBarUp = false
|   mEnterTransitionListener = android.app.SharedElementCallback$1@1891321968 (0x70bb4870)
|   mExitTransitionListener = android.app.SharedElementCallback$1@1891321968 (0x70bb4870)
|   mFinished = true
|   mFlipfont = 0
|   mFragments = android.app.FragmentController@856383904 (0x330b61a0)
|   mHandler = android.os.Handler@856395872 (0x330b9060)
|   mHasCurrentPermissionsRequest = false
|   mIdent = 226856808
|   mInstanceTracker = android.os.StrictMode$InstanceTracker@856383920 (0x330b61b0)
|   mInstrumentation = android.app.Instrumentation@851709880 (0x32c40fb8)
|   mIntent = android.content.Intent@858578880 (0x332cdfc0)
|   mLastNonConfigurationInstances = null
|   mMainThread = android.app.ActivityThread@851460448 (0x32c04160)
|   mManagedCursors = java.util.ArrayList@856308968 (0x330a3ce8)
|   mManagedDialogs = null
|   mMenuInflater = null
|   mParent = null
|   mPolicyManager = null
|   mReferrer = java.lang.String@856356128 (0x330af520)
|   mResultCode = -1
|   mResultData = null
|   mResumed = false
|   mScreenChangeListener = null
|   mSearchEvent = null
|   mSearchManager = null
|   mStartedActivity = false
|   mStopped = true
|   mTaskDescription = android.app.ActivityManager$TaskDescription@856395904 (0x330b9080)
|   mTemporaryPause = false
|   mTitle = java.lang.String@851901504 (0x32c6fc40)
|   mTitleColor = 0
|   mTitleReady = true
|   mToken = android.os.BinderProxy@856318080 (0x330a6080)
|   mTranslucentCallback = null
|   mUiThread = java.lang.Thread@1999246640 (0x772a1530)
|   mVisibleBehind = false
|   mVisibleFromClient = true
|   mVisibleFromServer = true
|   mVoiceInteractor = null
|   mWindow = com.android.internal.policy.PhoneWindow@860593808 (0x334b9e90)
|   mWindowAdded = true
|   mWindowManager = android.view.WindowManagerImpl@856400152 (0x330ba118)
|   mInflater = com.android.internal.policy.PhoneLayoutInflater@858279648 (0x33284ee0)
|   mOverrideConfiguration = null
|   mResources = android.content.res.Resources@858466752 (0x332b29c0)
|   mTheme = android.content.res.Resources$Theme@856384208 (0x330b62d0)
|   mThemeResource = 2131427510
|   mBase = android.app.ContextImpl@854679440 (0x32f15f90)
|   shadow$_klass_ = com.companyname.appname.activities.TaskCheckoutActivity
|   shadow$_monitor_ = 1073743558
* Excluded Refs:
| Field: android.view.inputmethod.InputMethodManager.mNextServedView
| Field: android.view.inputmethod.InputMethodManager.mServedView
| Field: android.view.inputmethod.InputMethodManager.mServedInputConnection
| Field: android.view.textservice.SpellCheckerSession$1.this$0
| Field: com.samsung.android.content.clipboard.SemClipboardManager.mContext
| Field: com.samsung.android.emergencymode.SemEmergencyManager.mContext
| Field: android.view.Choreographer$FrameDisplayEventReceiver.mMessageQueue (always)
| Thread:FinalizerWatchdogDaemon (always)
| Thread:main (always)
| Thread:LeakCanary-Heap-Dump (always)
| Class:java.lang.ref.WeakReference (always)
| Class:java.lang.ref.SoftReference (always)
| Class:java.lang.ref.PhantomReference (always)
| Class:java.lang.ref.Finalizer (always)
| Class:java.lang.ref.FinalizerReference (always)

我尝试过不使用smart-location-lib并实现代码来获取Android here官方培训文档中所写的当前位置。但这也会导致com.google.android.gms.internal.*内存泄漏。

我在两台设备(Android 7.0上的Galaxy S7和Android 5.1.1上的Galaxy J2 2016)上尝试了这一点,它们都会产生内存泄漏。该项目使用compile 'com.google.android.gms:play-services-location:11.2.2'

我做错了什么?

1 个答案:

答案 0 :(得分:1)

我在做动画时遇到像imageview,button等android.widget对象一样的问题所以我创建了静态内部类,而不是匿名或非静态内部类,而在静态我存储android.widget对象在一个弱的参考。

private static class ImageViewAnimation implements ValueAnimator.AnimatorUpdateListener {

    private final WeakReference<ImageView> mpetImageView;
    private int axis;

    public ImageViewAnimation(ImageView mpetImageView, int axis) {
        this.mpetImageView = new WeakReference<>(mpetImageView);
        this.axis = axis;
    }

    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        ImageView view = mpetImageView.get();
        int value = (int) valueAnimator.getAnimatedValue();
        if (this.axis == 1) {
            view.setTranslationX(value);
        } else if (this.axis == 2) {
            view.setTranslationY(value);
        }
    }
}

我在我的Activity中使用上面的类 petx.addUpdateListener(new ImageViewAnimation(petImageView, 1));

对于您的用例,此示例的内容将如下所示

  • 尝试创建一个静态内部类,并使其实现OnLocationUpdatedListener并在任何地方使用此类实例。
  • 确保您使用的android.Location实例mcurretLocation是非静态的
  • 尝试在onPause()onDestroy()
  • 中明确地使android.Location实例为null