我有一个非活动类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)
答案 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, 我会使用我提出的第一个建议。