Android:即使调用了removeUpdates,仍会出现LocationManager泄漏

3

我已经实现了一个片段,用于获取设备的GPS位置。但出现了内存泄漏问题——即使我注销了监听器(就像所有有关LocationManager内存泄漏的帖子中所建议的那样)。我对Android还是相对陌生的,可能是一些非常愚蠢的问题。

public class GetLocationTask extends Fragment {

/**
 * Callback interface through which the fragment will report the
 * task's progress and results back to the Activity. Calling activity MUST implement this.
 */
public interface LocationCallbacks {
    void onLocationReceived(double latitude, double longitude);
}

/** The calling activity. */
private LocationCallbacks mCallbacks;

private LocationManager locationManager;
private LocationListener locationListener;

/** Create a new instance. */
public static GetLocationTask newInstance() {
    GetLocationTask f = new GetLocationTask();

    // Supply index input as an argument.
    Bundle args = new Bundle();
    f.setArguments(args);

    return f;
}

@Override
public void onAttach(Context activity) {
    super.onAttach(activity);
    if (activity instanceof LocationCallbacks) {
        mCallbacks = (LocationCallbacks) activity;
    } else {
        Log.w("GetLocationTask", "CALLING CLASS DOES NOT IMPLEMENT INTERFACE!");
    }
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);

    locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
    locationListener = new LocationListener() {
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }

        public void onLocationChanged(Location location) {
            if (location != null) {
                double longitude = location.getLongitude();
                double latitude = location.getLatitude();

                locationManager.removeUpdates(locationListener);

                mCallbacks.onLocationReceived(latitude, longitude);
                Log.i("result", longitude +  "   >> " + latitude);
            } else {
                Log.i("waiting", "warming up still");
            }
        }
    };


    try {
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 90, locationListener);
    } catch (SecurityException e) {
        Log.i("TODO", "TODO");
    }

}

@Override
public void onDestroy() {
    super.onDestroy();
    if (locationManager != null && locationListener != null) {
        locationManager.removeUpdates(locationListener);
    }
    locationListener = null;
    locationManager = null;
}

@Override
public void onDetach() {
    super.onDetach();
    mCallbacks = null;
}
}

只是一点提示,我知道onDestroy正在调用“removeUpdates”,因为我在那里放了一个打印输出来确认它。 - Zee
好的,我所做的一切都没有解决这个问题。转而使用GoogleApiClient,看起来它运行良好。 - Zee
1个回答

2

您可以通过使locationListener不引用任何与fragment相关的内容来防止内存泄漏。

您可以将LocationListener创建为匿名类,因此它会引用您的fragment,并直接引用fragment的属性mCallbacks。

将locationListener定义为一个独立的类,在fragment中实例化它,然后将回调接口作为构造函数参数传递给监听器类,或者更好的方法是使用LiveData实例观察locationlistener(显然要使用fragment的lifecycleOwner进行观察)。


嗨@jhavatar!非常感谢您的帮助!我已经解决了这个问题(并且完全忘记了这个问题,所以没有来更新它),您是绝对正确的。从那时起,我实际上已经制作了一个单例来为我处理位置 - 我知道单例在Android中通常不是一件好事,但在这种情况下,如果单例被操作系统销毁,我并不介意 - 因为我不需要不断更新位置。再次感谢,注意安全 :) - Zee
1
今天遇到了同样的问题,@Zee :thumbsup: - jhavatar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接