0

My activity sometimes crashes when it goes out of view. It uses a LocationListener to receive location updates and show them on the screen. Here is the relevant code.

public class MyActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        lm = (LocationManager) getSystemService(LOCATION_SERVICE);
        tv = (TextView) findViewById(R.id.textView1);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
    }

    @Override
    protected void onStop() {
        lm.removeUpdates(listener);
        tv = null;
        lm = null;
        super.onStop();
    }

    private LocationManager lm;
    private TextView tv;
    private final LocationListener listener = new LocationListener() {

        @Override
        public void onLocationChanged(Location location) {
            tv.setText(location.getLatitude() + ", " + location.getLongitude());
        }

        @Override
        public void onProviderDisabled(String provider) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

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

    };

}

onLocationChanged() often gets called while tv is null, promptly causing a NullPointerException. I'm not setting tv to null anywhere other than onStop(), and the activity's mStopped is true according to the debugger. I suspect there's a race condition where location messages get enqueued on the main thread's Handler right as the activity is being stopped.

This behavior doesn't seem to be documented anywhere. How do I prevent onLocationChanged() from being called after onStop()?

Timothy003
  • 2,348
  • 5
  • 28
  • 33

2 Answers2

0

you can't. but you don't need to set your variables to null either.

njzk2
  • 38,969
  • 7
  • 69
  • 107
0

It's quite possible that something gets sent just before the activity stops since it gets sent asynchronously to the listener. I agree with @njzk2 in that you don't need to set your variables to null and you can create the variables in onCreate().

But also want to add that it's better to request and remove the updates in onResume() and onPause() since it's between these methods when the activity is visible to the user. You want to use the location services as little as possible.

Also, not related with the question but it's more standard to put the variables at the top (although it doesn't matter in Java)

pablisco
  • 14,027
  • 4
  • 48
  • 70
  • Thanks for your insight. I come from the C++ world, where the most visible members come first (public, then protected, then private). Is it also good practice in Java not to clean up your pointers? In this case, I have the extra burden of ensuring that whatever I put in `onLocationChanged()` can be executed at any time. This seems to share the same problem with [AsyncTask.](http://stackoverflow.com/questions/3357477/is-asynctask-really-massively-flawed-or-am-i-just-missing-something) – Timothy003 Oct 07 '11 at 18:24
  • One of great things of Java is the Garbage collector. It's a VM daemon on charge of picking up any objects that have no references (pointers) to them. In fact most of the time when your code goes out of scope (i.e. variable initiated inside an if clause) the local variables get automatically deallocated. Another thing to do to ensure the `Activity` can take the event is to check: [Finishing()](http://developer.android.com/reference/android/app/Activity.html#isFinishing()) – pablisco Nov 14 '11 at 15:50