我有一个简单的活动,我用一个按钮启动一个AsyncTask并用另一个停止它。
在AsyncTask中,我使用LocationListner从GPS传感器获取更新并计算获得的位置之间的距离。
当我按下开始按钮时,会创建新线程并且代码正常工作。在调试透视图中,我可以看到定期捕获GPS更新,并相应地更新我的变量。
但是,按下取消按钮时会出现问题。在文档(http://developer.android.com/reference/android/os/AsyncTask.html)中,我已经读过,当doInBackground代码完成时,cancel()方法应该调用onCancelled()。出于这个原因,我已经把:
if (isCancelled()){
locManager.removeUpdates(locListener);
}
遍布doInBackground方法,希望它能让我脱离它。不幸的是,我甚至没有达到那一部分。一旦我按下结束按钮,我会收到以下错误:
05-22 11:10:05.043: E/Handler(6353): java.lang.NullPointerException
05-22 11:10:05.043: E/Handler(6353): at com.pavle.taximetar.TaximetarActivity$2.onClick(TaximetarActivity.java:43)
05-22 11:10:05.043: E/Handler(6353): at android.view.View.performClick(View.java:3538)
05-22 11:10:05.043: E/Handler(6353): at android.view.View$PerformClick.run(View.java:14330)
05-22 11:10:05.043: E/Handler(6353): at android.os.Handler.handleCallback(Handler.java:607)
05-22 11:10:05.043: E/Handler(6353): at android.os.Handler.dispatchMessage(Handler.java:92)
05-22 11:10:05.043: E/Handler(6353): at android.os.Looper.loop(Looper.java:154)
05-22 11:10:05.043: E/Handler(6353): at android.app.ActivityThread.main(ActivityThread.java:4974)
05-22 11:10:05.043: E/Handler(6353): at java.lang.reflect.Method.invokeNative(Native Method)
05-22 11:10:05.043: E/Handler(6353): at java.lang.reflect.Method.invoke(Method.java:511)
05-22 11:10:05.043: E/Handler(6353): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
05-22 11:10:05.043: E/Handler(6353): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
05-22 11:10:05.043: E/Handler(6353): at dalvik.system.NativeStart.main(Native Method)
任何想法,这个错误背后是什么。这是完整的代码。 (构建目标是Android 4.0.3)。代码在HTC One V上进行测试。
public class TaximetarActivity extends Activity {
DistanceCalculator distanceCalculator;
public ArrayList<Drive> listOfRides = new ArrayList<Drive>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Button startRide = (Button) findViewById(R.id.button1);
final Button endRide = (Button) findViewById(R.id.button2);
startRide.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
distanceCalculator = new DistanceCalculator();
distanceCalculator.execute(getApplicationContext());
}
});
endRide.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
distanceCalculator.cancel(true);
}
});
}
}
public class DistanceCalculator extends AsyncTask<Context, Void, Void> {
Drive currentRide = new Drive();
Float distanceOfaRide = (float) 0;
LocationManager locManager;
LocationListener locListener;
Context mCtx;
boolean startPointEntered = false;
@Override
protected Void doInBackground(Context... params) {
mCtx = params[0];
Looper.prepare();
if (isCancelled()){
locManager.removeUpdates(locListener);
}
locManager = (LocationManager) mCtx.getSystemService(Context.LOCATION_SERVICE);
locListener = new LocationListener() {
public void onStatusChanged(String provider, int status, Bundle extras) {
if (isCancelled()){
locManager.removeUpdates(locListener);
}
}
public void onProviderEnabled(String provider) {
if (isCancelled()){
locManager.removeUpdates(locListener);
}
}
public void onProviderDisabled(String provider) {
if (isCancelled()){
locManager.removeUpdates(locListener);
}
}
public void onLocationChanged(Location location) {
if (DistanceCalculator.this.isCancelled()){
locManager.removeUpdates(locListener);
}
calculateDistance(location);
}
};
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, locListener);
Looper.loop();
return null;
}
@Override
protected void onCancelled() {
locManager.removeUpdates(locListener);
Intent intent = new Intent(mCtx, DisplayRide.class);
intent.putExtra("Distance", distanceOfaRide);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mCtx.startActivity(intent);
}
private void calculateDistance(Location location){
if (startPointEntered){
Location lastPoint = currentRide.drivePoints.get(currentRide.drivePoints.size()-1);
currentRide.addNewPoint(location);
distanceOfaRide = distanceOfaRide + location.distanceTo(lastPoint);
}
else{
currentRide.setStartPoint(location);
startPointEntered = true;
}
}
}
public class Drive {
Location startPoint;
Location endPoint;
ArrayList<Location> drivePoints = new ArrayList<Location>();
public Drive() {
// TODO Auto-generated constructor stub
}
public void setStartPoint(Location location){
startPoint = new Location(location);
drivePoints.add(0, startPoint);
}
public void setEndPoint(Location location){
endPoint = new Location(location);
}
public void addNewPoint(Location location){
drivePoints.add(location);
}
public Location getStartPoint(){
return startPoint;
}
}
答案 0 :(得分:0)
您在分配之前在locManager
上执行操作。
if (isCancelled()){
locManager.removeUpdates(locListener);
}
locManager = (LocationManager) mCtx.getSystemService(Context.LOCATION_SERVICE);
...对战
locManager = (LocationManager) mCtx.getSystemService(Context.LOCATION_SERVICE);
if (isCancelled()){
locManager.removeUpdates(locListener);
}
答案 1 :(得分:0)
问题出现在这部分代码中:
endRide.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
distanceCalculator.cancel(true);
}
});
这里,需要将消息发送到在Async任务中创建的处理程序。响应该消息,消息处理程序函数应取消该任务。