0

У меня есть простая деятельность, в которой я запускаю AsyncTask с помощью кнопки и останавливаю ее на другой.AsyncTask отменить метод порождает ошибку обработчика

В AsyncTask я использую LocationListner для получения обновлений от датчика GPS и расчета расстояния между полученными местоположениями.

Когда я нажимаю кнопку запуска, создается новый поток, и код работает нормально. В отладочной перспективе я вижу, что обновления GPS регулярно попадают, и мои переменные обновляются соответствующим образом.

Однако проблема начинается, когда я нажимаю кнопку отмены. В документации (http://developer.android.com/reference/android/os/AsyncTask.html) я прочитал, что метод cancel() должен вызывать onCancelled(), когда код doInBackground заканчивается. По этой причине я поставил:

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

Проблема была в этой части кода:

endRide.setOnClickListener(new OnClickListener() { 
    public void onClick(View v) { 
     distanceCalculator.cancel(true); 
    } 
}); 

Здесь требуется отправить сообщение в обработчик, который создается в задача Async. В ответ на это сообщение функция обработчика сообщений должна отменить задачу.

0

Вы выполняете действия на locManager, прежде чем вы присваиваете его.

if (isCancelled()){ 
    locManager.removeUpdates(locListener); 
} 

locManager = (LocationManager) mCtx.getSystemService(Context.LOCATION_SERVICE); 

Versus ...

locManager = (LocationManager) mCtx.getSystemService(Context.LOCATION_SERVICE); 
if (isCancelled()){ 
    locManager.removeUpdates(locListener); 
} 
+0

это не имеет значения, поскольку оператор if будет введен только тогда, когда задача async отменена. –

+0

в любом случае, спасибо за ваш ответ :) –

+0

Я вижу. я чувствую, что лучше всего назначать первое независимо. Никто не знает ;-) – Phix