Android 尝试中止时出现NetworkOnMainThreadException

Android 尝试中止时出现NetworkOnMainThreadException,android,Android,我有一个AsyncTask,它在从URL获取数据时弹出一个对话框,如果对话框被取消,它还有一个处理程序来取消请求。它在大多数情况下工作正常,但我发现它偶尔会因NetworkOnMainThreadException而崩溃。我的理论是,如果对话框在doInBackground()完成之后,但在onPostExecute()运行之前或运行时被取消,则CancelListener将在主线程上运行。那么这个理论有意义吗?我该如何正确处理它呢?试着抓住 下面是一个示例代码: public class Te

我有一个AsyncTask,它在从URL获取数据时弹出一个对话框,如果对话框被取消,它还有一个处理程序来取消请求。它在大多数情况下工作正常,但我发现它偶尔会因NetworkOnMainThreadException而崩溃。我的理论是,如果对话框在doInBackground()完成之后,但在onPostExecute()运行之前或运行时被取消,则CancelListener将在主线程上运行。那么这个理论有意义吗?我该如何正确处理它呢?试着抓住

下面是一个示例代码:

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
没有使用这个。