位置管理器removeUpdates NPE

时间:2014-10-08 12:26:29

标签: android android-lifecycle locationmanager

我有一个非活动类MyLocation搜索名为MainActivity的位置。当MainActivity为onPause()时,我想删除更新,但我得到一个NPE,因为listener = null即使它正在运行。我知道我可以用if捕获NPE,但我的问题是监听器为空的原因。

我正在调用MainActivity @ onPause()

MyLocation myLocation = new MyLocation(MainActivity.this, this);
myLocation.removeListener();

在MyLocation中,我启动了位置管理器,并希望停止使用方法removeListener()进行收听:

编辑:添加了MyLocation的完整代码:

    public class MyLocation {
    LocationManager lm;
    LocationManager lmNetwork;
    LocationManager lmGPS;
    LocationResult locationResult;
    boolean gps_enabled = false;
    boolean network_enabled = false;
    Context context;
    static Activity activity;
    private String gps, network, strLocationProvider;
    static ProgressDialog progress;

    private final int interval = 30000;
    private Handler handler = new Handler();
    private Handler handler2 = new Handler();

    public MyLocation(MainActivity context, MainActivity activity) {
        this.context = context;
        MyLocation.activity = activity;
    }

    public boolean getLocation(Context context, LocationResult result) {
        // Create a progress bar to display while the list loads
        showLoadingDialog();

        // I use LocationResult callback class to pass location value from
        // MyLocation to user code.
        locationResult = result;
        if (lm == null)
            lm = (LocationManager) context
            .getSystemService(Context.LOCATION_SERVICE);

        // exceptions will be thrown if provider is not permitted.
        try {
            network_enabled = lm
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        } catch (Exception ex) {
        }
        try {
            gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        } catch (Exception ex) {
        }

        // don't start listeners if no provider is enabled
        if (!gps_enabled && !network_enabled)
            enableLocationServices(context);

        if (network_enabled)
            System.out.println("Network => enabled");
        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
                locationListenerNetwork);

        if (gps_enabled)
            System.out.println("GPS => enabled");
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
                locationListenerGps);

        handler.postDelayed(locationfallback, interval);
        return true;
    }

    LocationListener locationListenerNetwork = new LocationListener() {
        public void onLocationChanged(Location location) {

            System.out
            .println("Provider => Network");

            locationResult.gotLocation(location);
            hideLoadingDialog();

            lm.removeUpdates(this);
            handler.removeCallbacks(locationfallback);

            //Continue searching for GPS for a defined time period
            handler2.postDelayed(GPSstopdelayed, interval);

        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };

    LocationListener locationListenerGps = new LocationListener() {

        public void onLocationChanged(Location location) {

            System.out
            .println("Provider => GPS");

            locationResult.gotLocation(location);
            hideLoadingDialog();

            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerNetwork);

            handler.removeCallbacks(locationfallback);

        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };

    //Schedule GPS listener
    private Runnable GPSstopdelayed = new Runnable() {

        @Override
        public void run() {
            lm.removeUpdates(locationListenerGps);
        }
    };

    //Fallback if listeners don't find any location until handler timer elapses
    private Runnable locationfallback = new Runnable() {

        @Override
        public void run() {

            lm.removeUpdates(locationListenerGps);
            lm.removeUpdates(locationListenerNetwork);

            try {
                LocationManager lm = (LocationManager) context
                        .getSystemService(Context.LOCATION_SERVICE);

                Criteria criteria = new Criteria();
                criteria.setAccuracy(Criteria.ACCURACY_FINE);
                criteria.setAltitudeRequired(false);
                criteria.setBearingRequired(false);
                criteria.setCostAllowed(true);
                criteria.setPowerRequirement(Criteria.POWER_LOW);
                strLocationProvider = lm.getBestProvider(criteria, true);

                System.out
                .println("FallbackLocationProvider => " + strLocationProvider);
                Location location = lm
                        .getLastKnownLocation(strLocationProvider);
                if (location != null) {
                    locationResult.gotLocation(location);
                    // Highlight GPS or Network icon
                    String usedProvider = location.getProvider();
                    if (usedProvider.equals("gps")) {
                        //Do something
                    }
                    if (usedProvider.equals("network")) {
                        //Do something else
                    }
                    hideLoadingDialog();

                }
                if (location == null) {
                    hideLoadingDialog();

                    Toast.makeText(
                            activity,context.getResources()
                            .getString(R.string.place_not_found),
                                    Toast.LENGTH_LONG).show();
                }
                return;

            } catch (Exception ex) {
                ex.printStackTrace();
            }

        }

    };

    public static abstract class LocationResult {
        public abstract void gotLocation(Location location);
    }

    public void enableLocationServices(final Context context) {

        // Show dialog to enable location services
        AlertDialog.Builder mAlertDialog = new AlertDialog.Builder(context);

        // Setting Dialog Title
        mAlertDialog
        // .setTitle(
        // context.getResources().getString(
        // R.string.location_not_available))
        .setMessage(
                context.getResources().getString(
                        R.string.enable_location_services))
                        .setPositiveButton(
                                context.getResources()
                                .getString(R.string.open_settings),
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog,
                                            int which) {
                                        Intent intent = new Intent(
                                                Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                        context.startActivity(intent);
                                        dialog.dismiss();
                                    }
                                }).show();
    }

    protected void removeListener() {
        handler.removeCallbacks(locationfallback);
        lm.removeUpdates(locationListenerGps);
        lm.removeUpdates(locationListenerNetwork);
    }

    protected void showLoadingDialog() {
        if (progress != null){
            progress.cancel();
            progress = ProgressDialog.show(activity, null, null, true, true);
            progress.setContentView(R.layout.progress_location_layout);
        } 
        if (progress == null){
            progress = ProgressDialog.show(activity, null, null, true, true);
            progress.setContentView(R.layout.progress_location_layout);
        }
    }

    protected void hideLoadingDialog() {
        if (progress != null && progress.isShowing()) {
            progress.cancel();
        }

    }

}

这是来自MainActivity的gotLocation(),它调用了一个显示位置的方法:

 LocationResult locationResult = new LocationResult() {
 @Override
 public void gotLocation(Location location) {
     if (location == null){
         tvcity.setText(R.string.notfound);
     }       
     if (location != null) {
         setLocation(location);
     }
 }
 };

这是日志:

10-08 14:16:22.805: W/dalvikvm(4939): threadid=1: thread exiting with uncaught  exception (group=0x40c87318)
10-08 14:16:22.805: E/AndroidRuntime(4939): FATAL EXCEPTION: main
10-08 14:16:22.805: E/AndroidRuntime(4939): java.lang.RuntimeException: Unable to pause activity {com.fleank.skybuddy/com.fleank.skybuddy.MainActivity}: java.lang.NullPointerException
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2842)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2798)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:2776)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread.access$800(ActivityThread.java:134)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.os.Handler.dispatchMessage(Handler.java:99)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.os.Looper.loop(Looper.java:137)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread.main(ActivityThread.java:4744)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at java.lang.reflect.Method.invokeNative(Native Method)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at java.lang.reflect.Method.invoke(Method.java:511)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at dalvik.system.NativeStart.main(Native Method)
10-08 14:16:22.805: E/AndroidRuntime(4939): Caused by: java.lang.NullPointerException
10-08 14:16:22.805: E/AndroidRuntime(4939):     at com.fleank.skybuddy.MyLocation.removeListener(MyLocation.java:131)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at com.fleank.skybuddy.MainActivity.onPause(MainActivity.java:457)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.Activity.performPause(Activity.java:5106)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1225)
10-08 14:16:22.805: E/AndroidRuntime(4939):     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2829)

1 个答案:

答案 0 :(得分:1)

看起来错误发生在MyLocation Class和MainActivity上, 我敢打赌,你启动了一个新的类实例,然后尝试访问位置监听器, 你能编辑你的帖子并发布MyLocation.java的整个代码吗? 我认为,如果您将保存对MyLocation实例的引用并在onPause()方法中调用该实例,它将起作用。

修改

您在onPause()方法中启动myLocation的新实例,并且正在该类启动位置侦听器, 这意味着您至少有两个myLocation实例,因此有两个LocaitonListener实例。您使用其中一个开始位置更新,然后尝试使用第二个停止它们。 您可以做的是保存我的位置的类变量,在onCreate上启动它并在onPause方法中使用它。 类似的东西:

public class MainActivity extends Activity {

    private MyLocation mMyLocation;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mMyLocation = new MyLocation(MainActivity.this, this);
    }

    @Override
    protected void onPause() {
        myLocation.removeListener();
        super.onPause();
    }
}

与您现在所做的非常类似的另一个选项是使用此处描述的Singleton设计模式: http://www.tutorialspoint.com/design_pattern/singleton_pattern.htm, 我会使用我提出的第一个建议。