android – 从onPause中的片段中删除位置更新时内存泄漏
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了android – 从onPause中的片段中删除位置更新时内存泄漏,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7809字,纯文字阅读大概需要12分钟。
内容图文
![android – 从onPause中的片段中删除位置更新时内存泄漏](/upload/InfoBanner/zyjiaocheng/956/7bfc9c026cde4438a506a2f17c2f438e.jpg)
在我的应用程序中的一个片段中,我需要位置更新,以确定用户何时接近一个简短的位置列表,以便用户可以获得相关信息.当我在onConnected()回调中使用创建位置更新请求时
LocationServices.FusedLocationApi.requestLocationUpdates(client, LocationRequest.create(), this);
我还使用了删除onPause()方法中的更新
LocationServices.FusedLocationApi.removeLocationUpdates(client, this);
然而,即使我调用该方法来删除位置更新,我也会从泄漏金丝雀那里得到警告,每当我离开该片段时,我的片段就会被泄露(所有片段导航都是使用replace()事务完成的).我在我的片段中启动位置请求时做错了什么,或者我没有在onPause()中正确清理请求,对此的任何帮助将不胜感激.
这是我的片段类的简化模型中的代码
public class BlankFragment extends Fragment implements GoogleApiClient.ConnectionCallbacks
, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private GoogleApiClient client;
private TextView textView;
public BlankFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_blank, container, false);
textView = (TextView) root.findViewById(R.id.location);
client = new GoogleApiClient.Builder(getContext())
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
return root;
}
@Override
public void onConnected(@Nullable Bundle bundle) {
startLocationUpdates();
}
private void startLocationUpdates() {
if (client.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(client, LocationRequest.create(), this);
}
}
private void stopLocationUpdates(){
LocationServices.FusedLocationApi.removeLocationUpdates(client, this);
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
public void onLocationChanged(Location location) {
textView.setText(location.toString());
}
@Override
public void onResume() {
startLocationUpdates();
super.onResume();
}
@Override
public void onPause() {
stopLocationUpdates();
super.onPause();
}
@Override
public void onStart() {
client.connect();
super.onStart();
}
@Override
public void onStop() {
if (client.isConnected()) {
client.disconnect();
}
super.onStop();
}}
此处还有生成的泄漏迹线
In com.example.testlocation:1.0:1.
* com.example.testlocation.BlankFragment has leaked:
* GC ROOT com.google.android.gms.internal.zzary$zzb.zzaGN
* references com.google.android.gms.internal.zzary$9.zzbkw (anonymous subclass of com.google.android.gms.internal.zzary$zza)
* leaks com.example.testlocation.BlankFragment instance
* Retaining: 7.1 KB.
* Reference Key: 720085d5-af68-42f3-a291-ef959e4c8ffa
* Device: Huawei google Nexus 6P angler
* Android Version: 7.1.2 API: 25 LeakCanary: 1.5 00f37f5
* Durations: watch=5031ms, gc=167ms, heap dump=1418ms, analysis=137993ms
* Details:
* Instance of com.google.android.gms.internal.zzary$zzb
| static $classOverhead = byte[240]@316980881 (0x12e4be91)
| zzaGN = com.google.android.gms.internal.zzary$9@316955016 (0x12e45988)
| mDescriptor = java.lang.String@317419776 (0x12eb7100)
| mObject = 483616889632
| mOwner = com.google.android.gms.internal.zzary$zzb@317493408 (0x12ec90a0)
| shadow$_klass_ = com.google.android.gms.internal.zzary$zzb
| shadow$_monitor_ = 0
* Instance of com.google.android.gms.internal.zzary$9
| static $classOverhead = byte[312]@317158785 (0x12e77581)
| zzbkw = com.example.testlocation.BlankFragment@316908800 (0x12e3a500)
| zzaxf = com.google.android.gms.common.api.Api@317047488 (0x12e5c2c0)
| zzazY = com.google.android.gms.common.api.Api$zzf@315109896 (0x12c83208)
| zzK = true
| zzaAh = java.lang.Object@315110136 (0x12c832f8)
| zzaAi = com.google.android.gms.internal.zzaaf$zza@317493376 (0x12ec9080)
| zzaAj = java.lang.ref.WeakReference@317491784 (0x12ec8a48)
| zzaAk = java.util.ArrayList@317491760 (0x12ec8a30)
| zzaAl = null
| zzaAm = java.util.concurrent.atomic.AtomicReference@317340960 (0x12ea3d20)
| zzaAn = null
| zzaAo = false
| zzaAp = false
| zzaAq = null
| zzaAr = null
| zzaAs = false
| zzair = com.google.android.gms.common.api.Status@317061968 (0x12e5fb50)
| zzazt = com.google.android.gms.common.api.Status@317061968 (0x12e5fb50)
| zztj = java.util.concurrent.CountDownLatch@317340944 (0x12ea3d10)
| shadow$_klass_ = com.google.android.gms.internal.zzary$9
| shadow$_monitor_ = -1987877821
* Instance of com.example.testlocation.BlankFragment
| static serialVersionUID = 8326097604377836997
| static $change = null
| static $classOverhead = byte[1168]@315449345 (0x12cd6001)
| client = com.google.android.gms.internal.zzaat@317202944 (0x12e82200)
| textView = android.support.v7.widget.AppCompatTextView@317036544 (0x12e59800)
| mAdded = false
| mAllowEnterTransitionOverlap = null
| mAllowReturnTransitionOverlap = null
| mAnimatingAway = null
| mArguments = null
| mBackStackNesting = 0
| mCalled = true
| mCheckedForLoaderManager = false
| mChildFragmentManager = null
| mChildNonConfig = null
| mContainer = null
| mContainerId = 0
| mDeferStart = false
| mDetached = false
| mEnterTransition = null
| mEnterTransitionCallback = android.app.SharedElementCallback$1@1883261776 (0x70404b50)
| mExitTransition = null
| mExitTransitionCallback = android.app.SharedElementCallback$1@1883261776 (0x70404b50)
| mFragmentId = 0
| mFragmentManager = null
| mFromLayout = false
| mHasMenu = false
| mHidden = false
| mHost = null
| mInLayout = false
| mIndex = -1
| mLoaderManager = null
| mLoadersStarted = false
| mMenuVisible = true
| mNextAnim = 0
| mParentFragment = null
| mReenterTransition = android.transition.TransitionSet@1883202880 (0x703f6540)
| mRemoving = false
| mRestored = false
| mRetainInstance = false
| mRetaining = false
| mReturnTransition = android.transition.TransitionSet@1883202880 (0x703f6540)
| mSavedFragmentState = null
| mSavedViewState = android.util.SparseArray@317491880 (0x12ec8aa8)
| mSharedElementEnterTransition = null
| mSharedElementReturnTransition = android.transition.TransitionSet@1883202880 (0x703f6540)
| mState = 0
| mStateAfterAnimating = 0
| mTag = null
| mTarget = null
| mTargetIndex = -1
| mTargetRequestCode = 0
| mUserVisibleHint = true
| mView = null
| mWho = null
| shadow$_klass_ = com.example.testlocation.BlankFragment
| shadow$_monitor_ = -2047550015
* Excluded Refs:
| 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)
解决方法:
即使在调用removeLocationUpdates之后,Google Maps SDK也会泄漏内存,这是一个长期存在的问题.你可以阅读更多关于它here.
以下解决方法为我删除了泄漏金丝雀通知.
1)创建一个WeakLocationListener类,它将位置监听器包装在弱引用中,然后使用该类来处理onLocationChanged回调.
public class WeakLocationListener implements LocationListener {
private final WeakReference<LocationListener> locationListenerRef;
public WeakLocationListener(@NonNull LocationListener locationListener) {
locationListenerRef = new WeakReference<>(locationListener);
}
@Override
public void onLocationChanged(android.location.Location location) {
if (locationListenerRef.get() == null) {
return;
}
locationListenerRef.get().onLocationChanged(location);
}
2)创建一个WeakLocationListener实例(使用您的片段实现的LocationListener)并在requestLocationUpdates和removeLocationUpdates时使用它 – 该位置将返回到您的activity / fragment(或任何正在实现LocationListener的类),并且泄漏金丝雀通知应该消失.
希望这可以帮助.
内容总结
以上是互联网集市为您收集整理的android – 从onPause中的片段中删除位置更新时内存泄漏全部内容,希望文章能够帮你解决android – 从onPause中的片段中删除位置更新时内存泄漏所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。