我在结束AsyncTask时遇到了麻烦,尽管我已经遵守了推荐的标志做法。下面的代码只考虑到了BackButton,但如果能有一个通用的解决方案来解决所有类型的退出活动,那将是最好的。
我有一个MeasurementLoadingsScreen类,它绑定了一个这样的Service。
ServiceConnection _connection = new ServiceConnection() {
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
_service = myService.Stub.asInterface(iBinder);
runMeasurementAsyncTask();
}
public void onServiceDisconnected(ComponentName componentName) {
_service = null;
}
};
@Override
protected void onStart() {
super.onStart();
Intent serviceIntent = new Intent();
serviceIntent.setPackage(myService.class.getPackage().getName());
serviceIntent.setAction(myService.class.getName() + ".ACTION_BIND");
bindService(serviceIntent, _connection, BIND_AUTO_CREATE);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_measurement_loadingscreen);
findViewsById();
setDefaultVisibility();
intent = getIntent();
//myStuff
}
MeasurementLoadingScreen包含一个带有WeakReference(或SoftReference,两种都试过)的AsyncTask。
private void runMeasurementAsyncTask() {
//myStuff
meTask = new MeasurementTask(this);
meTask.execute();
}
private static class MeasurementTask extends AsyncTask<Integer, Integer, String> {
private WeakReference<MeasurementLoadingScreen> activityReference;
private ServiceHelper serviceHelper;
//myStuff
public static boolean isRunning = false;
MeasurementTask(MeasurementLoadingScreen context) {
activityReference = new WeakReference<>(context);
serviceHelper = new ServiceHelper(context._service);
}
@Override
protected String doInBackground(Integer... params) {
MeasurementLoadingScreen activityReference = this.activityReference.get();
isRunning = true;
//myStuff, it's ok to finish running this before cancelling
if (isCancelled()) {
return "cancelled";
}
// more myStuff
if (isCancelled()) {
return "cancelled";
}
[...]
@Override
protected void onCancelled(){
//myStuff: safely shutdown measurement process, might take a few seconds at worst
meTask.isRunning = false;
if(activityReference.get() != null) {
activityReference.get().finish(); //it does not work without this, either
}
super.onCancelled();
}
当我向后点两次(不管具体行为如何),它应该(安全地)中止AsyncTask。
@Override
public void onBackPressed()
{
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
{
if (meTask == null) {
super.onBackPressed();
return;
}
cancelTask();
Toast.makeText(getBaseContext(), "Cancelling Task", Toast.LENGTH_SHORT).show();
return;
}
else { Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show(); }
mBackPressed = System.currentTimeMillis();
}
@Override
protected void onStop() {
super.onStop();
if (_connection != null)
unbindService(_connection);
finish();//
}
@Override
public void onPause() {
int i = 0;
super.onPause();
//poll state of task here
finish();
}
我似乎无法让任务停止运行。例如,如果我在onPause中设置meTask =null;,它最终会通过onCancelled,然后调用onStop,也结束服务。但是没有办法等onCancelled做完它的事情,然后用isRunningflag,getStatus或者其他什么东西来通知我。无论我如何轮询任务,这个应用都会冻结,而任务一直处于RUNNING状态,除非我把它设置为null(当然,这是不可取的)。
编辑:我已经添加了一个轮询尝试,让活动最终调用onPauseonStop,但我的主要问题是轮询,我从来没有看到一个finishfinishing任务,即使onCancelled在某些时候被调用,但只有在我设置meTask=null;之后,它才会正常继续取消。
public void onBackPressed() {
int i=0;
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
{
if (meTask == null) {
super.onBackPressed();
return;
}
cancelTask();
Toast.makeText(getBaseContext(), "Cancelling Task", Toast.LENGTH_SHORT).show();
while ((meTask.getStatus()== AsyncTask.Status.RUNNING) && (i < 20000)) {
//waiting etc., checking für isRunning doesn't work either
i++;
}
Log.d(TAG, "meTask " + meTask.getStatus());
meTask = null;
Log.d(TAG, "meTask null after " + i);
super.onBackPressed();
return;
Edit 2:
Content of cancelTask()
private void cancelTask() {
if (meTask != null) {
Log.d(TAG, "Async Task Cancel... ");
meTask.cancel(true);
}
}
编辑3:无论我把cancel(true)放在哪里,比如onPause,onStop,Task都会保持活力,并且只给我输出了以下的Log
if (isCancelled()) {
Log.d(TAG, "Cancel after XYZ");
return "cancelled";
}
和
@Override
protected void onCancelled() {
super.onCancelled();
isRunning = false;
Log.d(TAG, "...Async Task Cancelled ");
}
在最后,在onPause,onStop,onDestroy完成后。我束手无策。任务继续运行一会并不奇怪,但它必须在服务解绑前停止。如何才能等待任务结束?