FusedLocationProviderClient.removeLocationUpdates始终返回失败

时间:2017-12-08 05:19:51

标签: java android android-location

我有一个activity扩展名为class的{​​{1}} LocationAwareActivity LocationAwareActivity所有activity LocationServices.getFusedLocationProviderClient会创建一个位置服务客户端

listensremoveLocationUpdates来 位置更新。

此活动的来源是 https://github.com/snijsure/MultiActivity/blob/master/app/src/main/java/com/example/subodhnijsure/multiactivity/LocationAwareActivity.java

当活动被破坏时,它会调用removeLocationUpdate。我发现的是

  • activity返回始终返回不成功的任务
  • 更多的关注是因为没有删除位置活动,LocationAwareActivity没有被垃圾收集。

enter image description here - 因此,如果我启动从activity继承的任何活动,该活动始终保持在堆上。

所以问题是什么是停止接收位置更新的正确方法,从而允许<html> <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js"></script> <body> <div ng-app="app"> <div ng-controller="MainCtrl" ng-init="init()"> <input type="text" ng-model="listData"> </div> </div> </body> <script>var app = angular.module('app', []); app.controller('MainCtrl', function($scope) { $scope.init = function(){ $scope.list=[ { "name":"john", "types":[ {"work":"aa"}, {"work":"bb"} ] } ]; $scope.listData = ""; for(var i=0;i<$scope.list[0].types.length;i++){ if($scope.listData!= undefined){ $scope.listData = $scope.listData+","+$scope.list[0].types[i].work; } } } }); </script> </html>被垃圾收集。

此项目的整个来源可在此处访问 - https://github.com/snijsure/MultiActivity

4 个答案:

答案 0 :(得分:7)

removeLocationUpdates 中,您应该传递 locationCallback ,当前的实现是错误的。

但是,其他地方也有可能发生内存泄漏。您应该尝试在您的应用中集成Leakcanary,它可以为您提供参考树,并告诉您哪个字段或侦听器导致此内存泄漏。 您可以参考one of my only blog post here

My Training set and labels: 26721(each image have size (32, 32,1)) , (26721, 10) 
Validation set and labels:  6680(each image have size(32,32,1), (6680,10)

答案 1 :(得分:4)

您好@Subodh Nijsure请检查以下代码并粘贴到您的代码中并在检查后:

final Task<Void> voidTask = locationProviderClient.removeLocationUpdates(locationCallback);
                voidTask.addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        Log.e(TAG, "addOnCompleteListener: "+task.isComplete());
                    }
                });

                voidTask.addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        Log.e(TAG, "addOnSuccessListener: " );
                    }
                });

                voidTask.addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.e(TAG, "addOnFailureListener: ");
                    }
                });

我认为 voidTask.isSuccessful()当你把这个监听器放在那个时候它正常工作时这个方法不起作用我也看到内存它会释放所有内存来到上一个活动。

当你重定向到任何活动时,请将 stopLocationUpdates()一次调用到onPause()并从其他方法中删除,如onDestroy(),onStop()因为它停止一次所以我们为什么要这样做多次打电话。

希望这会对你有所帮助。

答案 2 :(得分:3)

Task对象返回false的原因在于stopLocationUpdates方法,您再次创建本地**LocationCallback**引用,然后将此引用用作locationProviderClient.removeLocationUpdates(cL);中的参数 您的本地LocationCallBack永远不会出现在locationProviderClient

所以你需要做的是,你必须传递你在startLocationUpdates方法中实例化的同一个全局对象,而不是创建另一个LocationCallBack对象

你的代码应该是这样的

inal Task<Void> voidTask = locationProviderClient.removeLocationUpdates(locationCallback);

答案 3 :(得分:3)

通过查看存储库中的代码,我发现您的设计中可能会导致Activity泄漏的一些问题。

1)您正在使用两个不同的LocationCallbacks。一个在开始,一个在停止方法,但你应该实际使用相同的。因此,一次实例化它就足够了,并且在删除Task时可能也会导致LocationCallback的成功结果。

2)由于您使用LocationCallback实例化Anonymous Class两次,即使您完成了包含类,也会保留内部类的非静态引用,这会导致您的Memory Leak 。您可以阅读有关此here的更多信息。

3)恕我直言,最好使用单独的经理类来处理您的位置请求,而不是抽象Activity

这就是说我的......

解决方案

<强> GpsManager.java

public class GpsManager extends LocationCallback {

    private FusedLocationProviderClient client;
    private Callback callback;

    public interface Callback {
        void onLocationResult(LocationResult locationResult);
    }

    public boolean start(Context context, Callback callback) {
        this.callback = callback;
        client = LocationServices.getFusedLocationProviderClient(context);
        if (!checkLocationPermission(context)) return false;
        client.requestLocationUpdates(getLocationRequest(), this, null);
        return true;
    }

    public void stop() {
        client.removeLocationUpdates(this);
    }

    @Override
    public void onLocationResult(LocationResult locationResult) {
        callback.onLocationResult(locationResult);
    }

    private boolean checkLocationPermission(Context context) {
        int permissionCheck = ContextCompat.checkSelfPermission(
                context, android.Manifest.permission.ACCESS_FINE_LOCATION);
        return permissionCheck == PackageManager.PERMISSION_GRANTED;
    }

    private LocationRequest getLocationRequest() {
        return LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(30_000L)
                .setFastestInterval(20_000L);
    }
}

并从Activity这样的

中调用此内容

<强> YourActivity.java

public class MapsActivity extends AppCompatActivity implements GpsManager.Callback  {

    private static final int PERMISSION_REQUEST_FINE_LOCATION = 1;
    private GpsManager mGpsManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        mGpsManager = new GpsManager(getApplicationContext(), this);

        // check if user gave permissions, otherwise ask via dialog
        if (!checkPermission()) {
            getLocationPermissions();
            return;
        }

        mGpsManager.start();
        ...
    }

    @Override
    protected void onStop() {
        super.onStop();
        mGpsManager.stop();
    }

    @Override
    public void onLocationResult(LocationResult locationResult) {
        // do something with the locationResult
    }

    // CHECK PERMISSIONS PART

    private boolean checkPermission() {
        return isGranted(ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION)) &&
                isGranted(ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION));
    }

    @TargetApi(Build.VERSION_CODES.M)
    private void getLocationPermissions() {
        requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION},
                PERMISSION_REQUEST_FINE_LOCATION);
    }

    @Override
    public void onRequestPermissionsResult(int code, @Nullable String permissions[], @Nullable int[] results) {
        switch (code) {
            case PERMISSION_REQUEST_FINE_LOCATION:
                if (isPermissionGranted(results)) {
                    getLocationRequest();
                }
        }
    }

    private boolean isPermissionGranted(int[] results) {
        return results != null && results.length > 0 && isGranted(results[0]);
    }

    private boolean isGranted(int permission) {
        return permission == PackageManager.PERMISSION_GRANTED;
    }
}

这只是一个猜测,因为我没有尝试您的代码,但解决方案应该会帮助您。如果我错了,请纠正我;)