Android 尝试中止时出现NetworkOnMainThreadException
我有一个AsyncTask,它在从URL获取数据时弹出一个对话框,如果对话框被取消,它还有一个处理程序来取消请求。它在大多数情况下工作正常,但我发现它偶尔会因NetworkOnMainThreadException而崩溃。我的理论是,如果对话框在doInBackground()完成之后,但在onPostExecute()运行之前或运行时被取消,则CancelListener将在主线程上运行。那么这个理论有意义吗?我该如何正确处理它呢?试着抓住 下面是一个示例代码:Android 尝试中止时出现NetworkOnMainThreadException,android,Android,我有一个AsyncTask,它在从URL获取数据时弹出一个对话框,如果对话框被取消,它还有一个处理程序来取消请求。它在大多数情况下工作正常,但我发现它偶尔会因NetworkOnMainThreadException而崩溃。我的理论是,如果对话框在doInBackground()完成之后,但在onPostExecute()运行之前或运行时被取消,则CancelListener将在主线程上运行。那么这个理论有意义吗?我该如何正确处理它呢?试着抓住 下面是一个示例代码: public class Te
public class TestTask extends AsyncTask<Void, Void, Void>
{
public ProgressDialog dialog;
public Context context;
public HttpUriRequest request;
public TestTask(Activity activity)
{
context = activity;
}
@Override
protected void onCancelled()
{
if (dialog != null)
dialog.dismiss();
super.onCancelled();
}
@Override
protected void onPreExecute()
{
OnCancelListener cancelListener = new OnCancelListener()
{
@Override
public void onCancel(DialogInterface dialog)
{
if (request != null)
request.abort(); // this causes NetworkOnMainThreadException sometimes
TestTask.this.cancel(true);
}
};
dialog = ProgressDialog.show(context, "", "Loading", true, true, cancelListener);
dialog.setCanceledOnTouchOutside(false);
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... params)
{
String url = "some url";
request = new HttpGet(url);
// process request
return null;
}
@Override
protected void onPostExecute(Void result)
{
dialog.dismiss();
super.onPostExecute(result);
}
}
公共类TestTask扩展了AsyncTask
{
公共对话;
公共语境;
公共HttpUriRequest请求;
公共测试任务(活动)
{
上下文=活动;
}
@凌驾
受保护的void onCancelled()
{
如果(对话框!=null)
dialog.dismise();
super.onCancelled();
}
@凌驾
受保护的void onPreExecute()
{
OnCancelListener cancelListener=新的OnCancelListener()
{
@凌驾
public void onCancel(对话框接口对话框)
{
if(请求!=null)
request.abort();//这有时会导致NetworkOnMainThreadException
TestTask.this.cancel(true);
}
};
dialog=ProgressDialog.show(上下文“,”加载“,”真、真、取消侦听器);
对话框。setCanceledOnTouchOutside(false);
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG\u保持屏幕打开);
super.onPreExecute();
}
@凌驾
受保护的Void doInBackground(Void…参数)
{
String url=“some url”;
请求=新的HttpGet(url);
//处理请求
返回null;
}
@凌驾
受保护的void onPostExecute(void结果)
{
dialog.dismise();
super.onPostExecute(结果);
}
}
我不会在这里尝试/捕获-这只会解决问题,在这种情况下不会执行中止。例如,您可以生成一个线程来执行中止尝试在中止之前取消请求
@Override
public void onCancel(DialogInterface dialog)
{
TestTask.this.cancel(true);
if (request != null)
request.abort(); // this causes NetworkOnMainThreadException sometimes
}
假设我的理论是正确的,那么请求就完成了,没有理由中止它。是否需要
request.abort()
?我以为cancel(true)
会中止线程。根据文档,cancel(true)告诉任务触发onCancelled()而不是onPostExecute(),这样在doInBackground()中发生的任何事情都会完成,这样请求就不会中止。他们确实建议在doInBackground()中放置一个循环来检查isCancelled(),但当在cancel上中止更有意义时,这对我来说似乎很奇怪。如果传递false,则是这样。但是,如果maybruptrunning==true
,它将调用thread.interrupt()
,检查FutureTask
的代码。这应该会让一切都停止。我运行了一个快速测试,看起来即使调用了cancel(true)
,请求仍会完成,所以任务可能会被中断,但请求不会。看起来你是对的。I/O阻塞应该被中断,但仅当它是java.nio.channels.interruptbleChannel
时。我猜HttpUriRequest
没有使用这个。