简体   繁体   English

Android-如何处理异步Http崩溃

[英]Android - How to Handle an Async Http Crash

My app is currently crashing whenever it cannot connect to the server. 我的应用程序当前无法连接服务器时崩溃。 How do I handle this, and instead let the user know that the server is down and to try again. 我该如何处理,而是让用户知道服务器已关闭并重试。

private void sendPostRequest(String givenEmail, String givenPassword) {

    class SendPostRequestTask extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {

            String emailInput = params[0];
            String passwordInput = params[1];

            String jsonUserInput = "{email: " + emailInput + ", password: "
                    + passwordInput + "}";

            try {

                HttpClient httpClient = new DefaultHttpClient();

                // Use only the web page URL as the parameter of the
                // HttpPost argument, since it's a post method.
                HttpPost httpPost = new HttpPost(SERVER_URL);

                // We add the content that we want to pass with the POST
                // request to as name-value pairs

                json = new JSONObject(jsonUserInput);

                jsonString = new StringEntity(json.toString());

                httpPost.setEntity(jsonString);

                httpPost.setHeader("Accept", "application/json");
                httpPost.setHeader("Content-type", "application/json");

                HttpParams httpParameters = httpPost.getParams();
                // Set the timeout in milliseconds until a connection is established.
                int timeoutConnection = 1000;
                HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
                // Set the default socket timeout (SO_TIMEOUT) 
                // in milliseconds which is the timeout for waiting for data.
                int timeoutSocket = 1000;
                HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

                // HttpResponse is an interface just like HttpPost.
                // Therefore we can't initialize them
                HttpResponse httpResponse = httpClient.execute(httpPost);

                // According to the JAVA API, InputStream constructor does
                // nothing.
                // So we can't initialize InputStream although it is not an
                // interface
                InputStream inputStream = httpResponse.getEntity()
                        .getContent();

                InputStreamReader inputStreamReader = new InputStreamReader(
                        inputStream);

                BufferedReader bufferedReader = new BufferedReader(
                        inputStreamReader);

                StringBuilder stringBuilder = new StringBuilder();

                String bufferedStrChunk = null;

                while ((bufferedStrChunk = bufferedReader.readLine()) != null) {
                    stringBuilder.append(bufferedStrChunk);
                }

                return stringBuilder.toString();

            } catch (ClientProtocolException cpe) {
                Log.i(LOGIN, "ClientProtocolException");
                cpe.printStackTrace();
            } catch (ConnectTimeoutException e) {
                e.printStackTrace();
            } catch (IOException ioe) {
                Log.i(LOGIN, "IOException");
                ioe.printStackTrace();
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);

            Log.i(LOGIN, result);

            try {
                serverResponse = new JSONObject(result);
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            try {
                if ((serverResponse.has("status"))
                        && (serverResponse.get("status").toString()
                                .equals("200"))) {
                    Toast.makeText(getApplicationContext(), "SUCCESS!",
                            Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(getApplicationContext(),
                            "Incorrect Email/Password!!!",
                            Toast.LENGTH_LONG).show();
                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    SendPostRequestTask sendPostRequestTask = new SendPostRequestTask();
    sendPostRequestTask.execute(givenEmail, givenPassword);
}

LogCat Error Log LogCat错误日志

11-11 16:26:14.970: I/R.id.login_button(17379): IOException 11-11 16:26:14.970: W/System.err(17379): org.apache.http.conn.HttpHostConnectException: Connection to http:// * refused 11-11 16:26:14.980: W/System.err(17379): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:183) 11-11 16:26:14.970:I / R.id.login_button(17379):IOException 11-11 16:26:14.970:W / System.err(17379):org.apache.http.conn.HttpHostConnectException到http:// *拒绝11-11 16:26:14.980:W / System.err(17379):位于org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:183)

I can see that you are already catching the Exceptions and have a String as parameter type to onPostExecute . 我可以看到您已经在捕获Exceptions ,并且将String作为onPostExecute参数类型。 From inside the exceptions, you can pass a string like "error" to the onPostExecute , whenever an error occurs. 在异常内部,只要发生错误,就可以将诸如“ error”之类的字符串传递给onPostExecute Inside the onPostExecute you can check: onPostExecute内,您可以检查:

if the string is equal to "error":
    then create a Alert dialog box from within `onPostExecute` and show it. 
else:
    continue as desired

Ideally a boolean would do the trick but since you already have a string, you can also use that. 理想情况下, boolean可以解决问题,但由于您已经有一个字符串,因此也可以使用它。 Otherwise you can have a struct with a string and a boolean and then pass it to onPostExecute . 否则,你可以有一个struct与一个字符串和一个布尔值,然后把它传递给onPostExecute Hope it gives you the idea. 希望它能给您带来灵感。

You can use droidQuery to simplify everything and include HTTP error handling: 您可以使用droidQuery简化一切,并包括HTTP错误处理:

$.ajax(new AjaxOptions().url("http://www.example.com")
                        .type("POST")
                        .dataType("json")
                        .header("Accept", "application/json")
                        .header("Content-type", "application/json")
                        .timeout(1000)
                        .success(new Function() {
                            @Override
                            public void invoke($ d, Object... args) {
                                Toast.makeText(this, "SUCCESS!", Toast.LENGTH_SHORT).show();
                                JSONObject serverResponse = (JSONObject) args[0];
                                //handle response
                            }
                        })
                        .error(new Function() {
                            @Override
                            public void invoke($ d, Object... args) {
                                AjaxError error = (AjaxError) args[0];
                                //toast shows the error code and reason, such as "Error 404: Page not found"
                                Toast.makeText(this, "Error " + error.status + ": " + error.reason, Toast.LENGTH_SHORT).show();
                            }
                        }));

Or you can create new Object 或者您可以创建新的对象

 public class AsyncTaskResult<T> {
    private T result;
    private Exception error;

    public T getResult() {
        return result;
    }
    public Exception getError() {
        return error;
    }

    public AsyncTaskResult(T result) {
        super();
        this.result = result;
    }

    public AsyncTaskResult(Exception error) {
        super();
        this.error = error;
    }

    public void setError(Exception error) {
        this.error = error;
    }
}

and pass it to onPostExecute 并将其传递给onPostExecute

return new AsyncTaskResult<String>(result)

or 要么

return new AsyncTaskResult<String>(exception)

in onPostExecute you may check exception exists or not onPostExecute您可以检查是否存在异常

asynctaskresult.getError() != null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM