2017-03-02 69 views
0

我是android開發中的新成員。如何在HTTP請求(RESTful web服務)中使用AsyncTask以避免ANR

現在我有公共類執行HTTP請求(REST Web服務)

的問題是,我不知道如何使用的AsyncTask所以每當請求過程需要很長的時間它使應用程序不響應和凍結。

這裏是我的代碼

public class RESTClient { 

private ArrayList<NameValuePair> params; 
private ArrayList <NameValuePair> headers; 

private String url; 

private int responseCode; 
private String message; 

private String response; 

public String getResponse() { 
    return response; 
} 

public String getErrorMessage() { 
    return message; 
} 

public int getResponseCode() { 
    return responseCode; 
} 

public enum RequestMethod 
{ 
    GET, 
    POST, 
    PUT, 
    DELETE 
} 

public RESTClient(String url) 
{ 
    this.url = url; 
    params = new ArrayList<NameValuePair>(); 
    headers = new ArrayList<NameValuePair>(); 
} 

public void AddParam(String name, String value) 
{ 
    params.add(new BasicNameValuePair(name, value)); 
} 

public void AddHeader(String name, String value) 
{ 
    headers.add(new BasicNameValuePair(name, value)); 
} 

public void Execute(RequestMethod method) throws Exception 
{ 
    switch(method) { 
     case GET: 
     { 
      //add parameters 
      String combinedParams = ""; 
      if(!params.isEmpty()){ 
       combinedParams += "?"; 
       for(NameValuePair p : params) 
       { 
        String paramString = URLEncoder.encode(p.getValue(), "UTF-8"); 
        if(combinedParams.length() > 1) 
        { 
         combinedParams += "|" + paramString; 
        } 
        else 
        { 
         combinedParams += paramString; 
        } 
       } 
      } 

      HttpGet request = new HttpGet(url); 
      executeRequest(request, url); 
      break; 
     } 
     case POST: 
     { 
      HttpPost request = new HttpPost(url); 

      //add headers 
      for(NameValuePair h : headers) 
      { 
       request.addHeader(h.getName(), h.getValue()); 
      } 

      if(!params.isEmpty()){ 
       NameValuePair param = params.get(0); 
       String val = param.getValue(); 

       StringEntity data = new StringEntity("{\"Value\": \"" + val + "\"}"); 
       data.setContentType("application/json"); 
       request.setEntity(data); 
      } 

      executeRequest(request, url); 
      break; 
     } 
     case PUT: 
     { 
      HttpPut request = new HttpPut(url); 

      //add headers 
      for(NameValuePair h : headers) 
      { 
       request.addHeader(h.getName(), h.getValue()); 
      } 

      if(!params.isEmpty()){ 
       NameValuePair param = params.get(0); 
       String val = param.getValue(); 

       StringEntity data = new StringEntity("{\"Value\": \"" + val + "\"}"); 
       data.setContentType("application/json"); 
       request.setEntity(data); 
      } 

      executeRequest(request, url); 
      break; 
     } 
     case DELETE: 
     { 
      HttpDelete request = new HttpDelete(url); 

      //add parameters 
      String combinedParams = ""; 
      if(!params.isEmpty()){ 
       combinedParams += "?"; 
       for(NameValuePair p : params) 
       { 
        String paramString = URLEncoder.encode(p.getValue(), "UTF-8"); 
        if(combinedParams.length() > 1) 
        { 
         combinedParams += "|" + paramString; 
        } 
        else 
        { 
         combinedParams += paramString; 
        } 
       } 
      } 

      executeRequest(request, url); 
      break; 
     } 
    } 
} 

private void executeRequest(HttpUriRequest request, String url) 
{ 

    HttpClient client = new DefaultHttpClient(); 

    HttpResponse httpResponse; 
    try { 

     StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
     StrictMode.setThreadPolicy(policy); 
     httpResponse = client.execute(request); 
     responseCode = httpResponse.getStatusLine().getStatusCode(); 
     message = httpResponse.getStatusLine().getReasonPhrase(); 

     HttpEntity entity = httpResponse.getEntity(); 

     if (entity != null) { 

      InputStream instream = entity.getContent(); 
      response = convertStreamToString(instream); 

      // Closing the input stream will trigger connection release 
      instream.close(); 
     } 

    } catch (ClientProtocolException e) { 
     client.getConnectionManager().shutdown(); 
     e.printStackTrace(); 
    } catch (IOException e) { 
     client.getConnectionManager().shutdown(); 
     e.printStackTrace(); 

    } 
} 


private static String convertStreamToString(InputStream is) { 

    BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 
    StringBuilder sb = new StringBuilder(); 

    String line = null; 
    try { 
     while ((line = reader.readLine()) != null) { 
      sb.append(line); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      is.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
    return sb.toString(); 
} 
} 

有沒有什麼辦法,包括的AsyncTask過程變成我的課?

--EDITED--使用狂sciendtist

public class RESTClient { 

private ArrayList<NameValuePair> params; 
private ArrayList <NameValuePair> headers; 
private String url; 
private int responseCode; 
private String message; 

ProgressDialog progressBar; 
private String response; 
private Context mContext; 

public String getResponse() { 
    return response; 
} 

public String getErrorMessage() { 
    return message; 
} 

public int getResponseCode() { 
    return responseCode; 
} 

public enum RequestMethod 
{ 
    GET, 
    POST, 
    PUT, 
    DELETE 
} 

public RESTClient(String url) 
{ 
    this.url = url; 
    params = new ArrayList<NameValuePair>(); 
    headers = new ArrayList<NameValuePair>(); 
} 

public void AddParam(String name, String value) 
{ 
    params.add(new BasicNameValuePair(name, value)); 
} 

public void AddHeader(String name, String value) 
{ 
    headers.add(new BasicNameValuePair(name, value)); 
} 

    public String Execute(RequestMethod method) throws Exception 
    { 
     switch(method) { 
      case GET: 
      { 
       //add parameters 
       String combinedParams = ""; 
       if(!params.isEmpty()){ 
        combinedParams += "?"; 
        for(NameValuePair p : params) 
        { 
         String paramString = URLEncoder.encode(p.getValue(), "UTF-8"); 
         if(combinedParams.length() > 1) 
         { 
          combinedParams += "|" + paramString; 
         } 
         else 
         { 
          combinedParams += paramString; 
         } 
        } 
       } 

       HttpGet request = new HttpGet(url); 
       // IM CALLING THE ASYNCTASK HERE 
       return new HttpRequest(request, url).get(); 

       break; 
      } 
      default: 
       return ""; 
      break; 

     } 
    } 
private void executeRequest(HttpUriRequest request, String url) 
{ 
    HttpClient client = new DefaultHttpClient(); 

    HttpResponse httpResponse; 
    try { 

     StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
     StrictMode.setThreadPolicy(policy); 
     httpResponse = client.execute(request); 
     responseCode = httpResponse.getStatusLine().getStatusCode(); 
     message = httpResponse.getStatusLine().getReasonPhrase(); 

     HttpEntity entity = httpResponse.getEntity(); 

     if (entity != null) { 

      InputStream instream = entity.getContent(); 
      response = convertStreamToString(instream); 

      // Closing the input stream will trigger connection release 
      instream.close(); 
     } 

    } catch (ClientProtocolException e) { 
     client.getConnectionManager().shutdown(); 
     e.printStackTrace(); 
    } catch (IOException e) { 
     client.getConnectionManager().shutdown(); 
     e.printStackTrace(); 

    } 
} 


private static String convertStreamToString(InputStream is) { 

    BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 
    StringBuilder sb = new StringBuilder(); 

    String line = null; 
    try { 
     while ((line = reader.readLine()) != null) { 
      sb.append(line); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      is.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
    return sb.toString(); 
} 

private class HttpRequest extends AsyncTask<HttpUriRequest,Void, String> { 

    private HttpUriRequest httpUriRequest; 
    private String url; 
    public HttpRequest(HttpUriRequest httpUriRequest , String url) { 
     this.httpUriRequest = httpUriRequest; 
     this.url = url; 
    } 

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

     // perform all network task on a different thread (i.e not on the main thread) 
     HttpClient client = new DefaultHttpClient(); 
     String response=null; 
     HttpResponse httpResponse; 
     try { 

      StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
      StrictMode.setThreadPolicy(policy); 
      httpResponse = client.execute(httpUriRequest); 
      responseCode = httpResponse.getStatusLine().getStatusCode(); 
      message = httpResponse.getStatusLine().getReasonPhrase(); 

      HttpEntity entity = httpResponse.getEntity(); 

      if (entity != null) { 

       InputStream instream = entity.getContent(); 
       response = convertStreamToString(instream); 

       // Closing the input stream will trigger connection release 
       instream.close(); 
      } 

     } catch (ClientProtocolException e) { 
      client.getConnectionManager().shutdown(); 
      e.printStackTrace(); 
     } catch (IOException e) { 
      client.getConnectionManager().shutdown(); 
      e.printStackTrace(); 

     } 
     // return the response; 
     return response; 
    } 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
     // do not forget to add a progress dialog here or a progressbar 

    } 

    @Override 
    protected void onPostExecute(String s) { 
     super.onPostExecute(s); 
     if (!TextUtils.isEmpty(s)){ 
      // on succesfull callback. hide the progres bar or dialog 

     } 
    } 


} 

}

,這是我的活動異步調用時RESTClient實現,我需要獲得響應回JSON

後登錄.Java

public class Login extends AppCompatActivity { 

private static String URLService; 
// UI references. 
private EditText USERID; 
private EditText PASSWORD; 
private View mProgressView; 
private View mLoginFormView; 
public static String UserID; 
private static String Version="3.0"; 
private String VersionID; 
private String VersionStatus; 
private String hashed=""; 
private String Enc_Pass=""; 
private int responseCode; 
Context context; 
ProgressDialog mProgressDialog; 
private String message; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_login); 
    // Set up the login form. 
    USERID = (EditText)findViewById(R.id.userID); 
    //populateAutoComplete(); 
    URLService = getString(R.string.URLService); 
    Enc_Pass = getString(R.string.password_encryption); 
    PASSWORD = (EditText) findViewById(R.id.password); 
    Button LOGINBUTTON = (Button) findViewById(R.id.email_sign_in_button); 
    LOGINBUTTON.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      attemptLogin(); 
     } 
    }); 

    mProgressView = findViewById(R.id.login_progress); 
    SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", MODE_PRIVATE); 
    UserID = pref.getString("userId", ""); 
    if (!UserID.toString().equals("")) 
    { 
     Intent i = new Intent(Login.this, Index.class); 
     startActivity(i); 
    } 
    else 
    { 
    } 
} 
private void attemptLogin() { 

    // Reset errors. 
    USERID.setError(null); 
    PASSWORD.setError(null); 
    // Store values at the time of the login attempt. 

     try { 
      String valueEncrypt = strUserId + "|" + strPassword; 
      String encc = ""; 
      try { 
        encc = AndroidCrypt.encrypt(Enc_Pass,valueEncrypt); 
        encc = encc.replace("+", "%2B"); 
      }catch (GeneralSecurityException e){ 
       //handle error 
      } 

     //  new BigProccess(Login.this, ProgressDialog.STYLE_SPINNER).execute(); 
      // new HttpRequestMet(URLService+"do?method=dologin&value=" +encc,"GET").execute(); 
      RESTClient client = new RESTClient(URLService+"do?method=dologin&value=" +encc); 

      client.Execute(RESTClient.RequestMethod.GET); 

      String response = client.getResponse(); 

      response = response.replace("\\\"", "\""); 
      response = response.substring(1, response.length() - 1); 

      JSONParser jsonParser = new JSONParser(); 
      JSONObject jsonObject = (JSONObject) jsonParser.parse(response); 
      Status = jsonObject.get("Status").toString(); 

      if (Status == "true") { 

       String dataku = jsonObject.get("Data").toString(); 

       try { 
       dataku = AndroidCrypt.decrypt(Enc_Pass, dataku); 
       }catch (GeneralSecurityException e){ 
        //handle error - could be due to incorrect password or tampered encryptedMsg 
       } 

       JSONParser parser = new JSONParser(); 
       JSONObject structure = (JSONObject) parser.parse(dataku); 


       Toast.makeText(getApplicationContext(), "Welcome Back Mr./Mrs. " + FullName, 
         Toast.LENGTH_SHORT).show(); 

       Intent i = new Intent(Login.this, Index.class); 
       startActivity(i); 
       // finish(); 



      } else { 
       Toast.makeText(getApplicationContext(), "Login Failed", 
         Toast.LENGTH_SHORT).show(); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
      Toast.makeText(getApplicationContext(),"Cant Connect to server, please try again later", 
        Toast.LENGTH_SHORT).show(); 
     } 
    } 


} 

}

+0

本機方式,如果你不跟熟悉並且嘗試AsycnTask與截擊。 –

+0

如果您不熟悉Android開發,請先不要使用已棄用的類,例如NameValuePair(API level 23以後,它已被刪除,棉花糖) – Massimo

回答

0

簡單地說你的網絡操作的的AsyncTask內,

class HTTPAsyncTask extends AsyncTask<String, Void, Boolean> { 

@Override 
protected void onPreExecute() { 
    super.onPreExecute(); 

} 

@Override 
protected Boolean doInBackground(String... urls) { 
    HttpGet request = new HttpGet(url); 
    executeRequest(request, url); 
    return false; 
} 

protected void onPostExecute(Boolean result) { 

} 

要在類寫的任何地方執行的AsyncTask,

new HTTPAsyncTask().execute(""); 
+0

對不起,您能否在我的代碼中實現,我還是不明白?或者我必須上新班? – gilllsss

0

歡迎Android開發人員,有一個在Android的一個主線程(UI線程)所有視圖操作發生的地方。建議不要在這些線程上執行繁重的計算或文件系統操作或NetworkTasks,因爲視圖依賴於此線程。

那麼作爲解決這個問題,Android有對Worker threads支持,作出處理這些沉重的操作。

AsyncTask是實現這種結構的好方法。 Read the doc here

至於你的代碼的話,你可以在同一個文件

private class HttpRequest extends AsyncTask<Void,Void, String>{ 

private HttpUriRequest httpUriRequest; 
private String url; 
public HttpRequest(HttpUriRequest httpUriRequest , String url) { 
    this.httpUriRequest = httpUriRequest; 
    this.url = url; 
} 

@Override 
protected void onPreExecute() { 
    super.onPreExecute(); 
    // do not forget to add a progress dialog here or a progressbar 
    progressBar.show(); 
} 

@Override 
protected void onPostExecute(String s) { 
    super.onPostExecute(s); 
    if (!TextUtils.isEmpty(s)){ 
     // on succesfull callback. hide the progres bar or dialog 
     progressBar.gone(); 
    } 
} 

@Override 
protected String doInBackground(Void... voids) { 

    // perform all network task on a different thread (i.e not on the main thread) 
    HttpClient client = new DefaultHttpClient(); 
    String response=null; 
    HttpResponse httpResponse; 
    try { 

     StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
     StrictMode.setThreadPolicy(policy); 
     httpResponse = client.execute(request); 
     responseCode = httpResponse.getStatusLine().getStatusCode(); 
     message = httpResponse.getStatusLine().getReasonPhrase(); 

     HttpEntity entity = httpResponse.getEntity(); 

     if (entity != null) { 

      InputStream instream = entity.getContent(); 
      response = convertStreamToString(instream); 

      // Closing the input stream will trigger connection release 
      instream.close(); 
     } 

    } catch (ClientProtocolException e) { 
     client.getConnectionManager().shutdown(); 
     e.printStackTrace(); 
    } catch (IOException e) { 
     client.getConnectionManager().shutdown(); 
     e.printStackTrace(); 

    } 
    // return the response; 
    return response; 
} 
} 

創建一個新的類和所有你需要做的就是使用自定義Contructor

前呼叫發起這一類。 new HttpRequest(httpUriRequest, url).execute();並處理onPostExecute()方法中的響應。

而且,因爲你是新的,小的建議,嘗試的第一個字母爲小寫一個,這樣你就可以從它的方法來區分一類的命名方法名。

並嘗試Retrofit它的方式冷靜然後HTTPRequests的

+0

海,我試過,但它不直接去doInBackground,我不知道爲什麼。所以我首先得到catch例外。也沒有得到迴應 – gilllsss

+0

你可以發佈異常嗎?還有你的原始代碼。嘗試使用[Pastebin](http://pastebin.ubuntu.com/) – MadScientist

+0

我已經更新我的文章,請檢查。還需要將響應返回給我的活動以獲取json數據。我怎樣才能做到這一點? thx b4 – gilllsss