我正在使用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'
我做错了什么?
答案 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
并在任何地方使用此类实例。mcurretLocation
是非静态的onPause()
或onDestroy()