Android:使用简单的警报对话框处理AsyncTask中的SocketTimeoutException

时间:2016-01-06 16:22:37

标签: java android android-asynctask alertdialog

我在Android应用中使用AsyncTask从服务器获取一些数据。要建立连接,我使用HttpURLConnection类,超时为10秒。现在,我想在(如果)该时间到期时显示一个简单的AlertDialog,使用OK按钮将用户带回到Main Activity。现在,这就是我的应用程序(DoorActivity)的相关部分:

    protected String doInBackground(String... params) {

        try {

            URL url = new URL(params[0]);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setConnectTimeout(10000);
            urlConnection.setRequestMethod("GET");
            if (urlConnection.getResponseCode() != 200) {
                throw new IOException(urlConnection.getResponseMessage());
            }

            BufferedReader read = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
            jsonString = read.readLine().toString();

        } catch (MalformedURLException malformedUrlException) {
            System.out.println(malformedUrlException.getMessage());
            malformedUrlException.printStackTrace();

        } catch (SocketTimeoutException connTimeout) {
            showTimeoutAlert();

showTimeoutAlert()方法位于DoorActivity的根类中,如下所示:

protected void showTimeoutAlert(){
    TextView timeoutWarning = new TextView(this);
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    AlertDialog alertDialog;
    timeoutWarning.setText(R.string.conn_timeout_warning);
    builder.setView(timeoutWarning);
    builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            Intent intent = new Intent(DoorActivity.this, MainActivity.class);
            startActivity(intent);
        }
    });
    alertDialog = builder.create();
    alertDialog.show();
}

现在,当我运行此应用程序时,服务器故意脱机,我得到以下异常:

java.lang.RuntimeException:执行doInBackground()时发生错误

引起:java.lang.RuntimeException:无法在未调用Looper.prepare()的线程内创建处理程序

3 个答案:

答案 0 :(得分:2)

不应在showTimeoutAlert();中调用{p> doInBackground()。与UI相关的任何代码都应改为onPostExecute()

例如:

private boolean socketTimedOut = false;

@Override
protected String doInBackground(String... params) {
    try {
        ...
    } catch (SocketTimeoutException connTimeout) {
        this.socketTimedOut = true;
    }
}


@Override
protected void onPostExecute(String result) {
    if(this.socketTimedOut){
        showTimeoutAlert();
    }
}

替代解决方案(不推荐):

@Override
protected String doInBackground(String... params) {
    try {
        ...
    } catch (SocketTimeoutException connTimeout) {
        runOnUiThread(new Runnable() {
            public void run() {
                showTimeoutAlert();
            }
        });
    }
}       

答案 1 :(得分:0)

您无法在doInBackground方法中显示弹出窗口/对话框。如果出现任何异常,则返回null并检查postExecute方法中的返回值。在那里,您可以显示相关的弹出/对话框

答案 2 :(得分:0)

您必须在postExecute方法中调用showTimeoutAlert(),因为您无法在doInBackground对话框中更改UI。返回一个relsut,然后在那里调用该方法。