2014-03-27 21 views
0

。嗨,作爲一個年輕的android開發者,我正在尋找一種從服務器獲取JSON響應的方法。 我開始尋找AsyncTask,但我不太願意爲每次需要詢問WebService時編寫一個AsyncTask。Java:在AsyncTask中嵌入的WebService請求

然後我開始編寫一個查詢URL(POST或GET)的類(擴展AsyncTask)並提供一個包含來自服務器的響應的回調。 我想獲得一些反饋,是否真的有用,而不是一個無用的AsyncTask疊加,因爲我錯過了一些理解。 越是我編碼,我越懷疑。

在此先感謝您的意見。

這裏是我用來查詢服務器與我的類的代碼:

HashMap<String, String> parameters = new HashMap<String, String>(); 
parameters.put("address", "sidney"); 
parameters.put("sensor", "false"); 

WebServiceAsyncTask asyncWS = new WebServiceAsyncTask(MainActivity.this); 
asyncWS.setParameters(parameters); 
asyncWS.execute(
     "http://maps.googleapis.com/maps/api/geocode/json", 
     WebServiceAsyncTask.GET, 
     new WebServiceAsyncTaskCallback() { 
      @Override 
      void callbackMethod(String result) { 
       Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show(); 
      } 
     } 
); 

這裏是我的WebServiceAsyncTask的代碼:

import android.app.ProgressDialog; 
import android.content.Context; 
import android.net.Uri; 
import android.os.AsyncTask; 
import org.apache.http.HttpResponse; 
import org.apache.http.NameValuePair; 
import org.apache.http.StatusLine; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.message.BasicNameValuePair; 
import org.apache.http.protocol.HTTP; 
import org.apache.http.util.EntityUtils; 

import java.io.UnsupportedEncodingException; 
import java.net.HttpURLConnection; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 

/** 
* Anthony Raymond 
*/ 
public class WebServiceAsyncTask extends AsyncTask<Object, String, String> { 
    public static final String GET = "GET"; 
    public static final String POST = "POST"; 

    private static final String PROGRESS_TEXT_PREPARING = "Preparing request"; 
    private static final String PROGRESS_PERCENT_PREPARING = "25"; 
    private static final String PROGRESS_TEXT_CONNECTION_SERVER = "Connecting to the server"; 
    private static final String PROGRESS_PERCENT_CONNECTION_SERVER = "50"; 
    private static final String PROGRESS_TEXT_PARSING = "Parsing received data"; 
    private static final String PROGRESS_PERCENT_PARSING = "75"; 
    private static final String PROGRESS_TEXT_END = "Process ended"; 
    private static final String PROGRESS_PERCENT_END = "100"; 


    private Context context; 
    private HashMap<String, String> mData = new HashMap<String, String>(); 
    private ProgressDialog progressDialog; 


    private WebServiceAsyncTaskCallback callbackClass; 

    /** 
    * If a Context is passed, a ProgressDialog will be displayed 
    * NEED TO PASS Context LIKE THIS : 
    * MyActivity.this 
    * DO NOT USE getApplicationContext() 
    * @param applicationContext 
    */ 
    public WebServiceAsyncTask(Context applicationContext) 
    { 
     this.context = applicationContext; 
    } 

    /** 
    * Create a WebServiceAsyncTask. 
    * Usage : add request parameter by passing an HashMap<String, String> with the setParameter Method, then call 
    * .execute(String url, WebServiceAsyncTask constant (GET or SET), WebServiceAsyncTaskCallback callback) 
    * exemple : 
    * HashMap<String, String> parameters = new HashMap<String, String>(); 
    * parameters.put("address", "Sidney"); 
    * parameters.put("sensor", "false"); 
    * WebServiceAsyncTask asyncWS = new WebServiceAsyncTask(MainActivity.this); 
    * asyncWS.setParameters(parameters); 
    * asyncWS.execute(
    *  "http://maps.googleapis.com/maps/api/geocode/json", 
    *  WebServiceAsyncTask.GET, 
    *  new WebServiceAsyncTaskCallback() { 
    *   @Override 
    *   void callbackMethod(String result) { 
    *    Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show(); 
    *   } 
    *  } 
    *); 
    */ 
    public WebServiceAsyncTask() 
    { 
     this.context = null; 
    } 

    private void prepareProgressDialog() 
    { 
     if (this.context != null) 
     { 
      this.progressDialog = new ProgressDialog(this.context); 
      this.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
      this.progressDialog.setCancelable(true); 
      this.progressDialog.setTitle("Please Wait..."); 
      this.progressDialog.setMessage(PROGRESS_TEXT_PREPARING); 
      this.progressDialog.setProgress(Integer.parseInt(PROGRESS_PERCENT_PREPARING)); 
     } 
    } 
    private String getPostResponse(String url) 
    { 
     byte[] result; 
     String str = ""; 
     HttpClient client = new DefaultHttpClient(); 

     HttpPost http = new HttpPost(url); 
     // set up post data 
     List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(); 
     for (String key : this.mData.keySet()) { 
      nameValuePair.add(new BasicNameValuePair(key, this.mData.get(key))); 
     } 

     UrlEncodedFormEntity urlEncodedFormEntity; 
     try 
     { 

      urlEncodedFormEntity = new UrlEncodedFormEntity(nameValuePair); 
      http.setEntity(urlEncodedFormEntity); 
      this.publishProgress(PROGRESS_TEXT_CONNECTION_SERVER, PROGRESS_PERCENT_CONNECTION_SERVER); 
      HttpResponse response = client.execute(http); 
      StatusLine statusLine = response.getStatusLine(); 

      if(statusLine.getStatusCode() == HttpURLConnection.HTTP_OK) 
      { 
       this.publishProgress(PROGRESS_TEXT_PARSING, PROGRESS_PERCENT_PARSING); 
       result = EntityUtils.toByteArray(response.getEntity()); 
       str  = new String(result, HTTP.UTF_8); 
      } 
     } 
     catch (UnsupportedEncodingException e) 
     { 
      e.printStackTrace(); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     return str; 
    } 
    private String getGetResponse(String url) 
    { 
     byte[] result; 
     String str = ""; 
     HttpClient client = new DefaultHttpClient(); 

     try 
     { 
      // set up get data and URL 
      Uri.Builder uri = Uri.parse(url).buildUpon(); 

      for (String key : this.mData.keySet()) { 
       uri.appendQueryParameter(key, this.mData.get(key)); 
      } 

      HttpGet http = new HttpGet(String.valueOf(uri)); 
      this.publishProgress(PROGRESS_TEXT_CONNECTION_SERVER, PROGRESS_PERCENT_CONNECTION_SERVER); 
      HttpResponse response = client.execute(http); 
      StatusLine statusLine = response.getStatusLine(); 

      if(statusLine.getStatusCode() == HttpURLConnection.HTTP_OK) 
      { 
       this.publishProgress(PROGRESS_TEXT_PARSING, PROGRESS_PERCENT_PARSING); 
       result = EntityUtils.toByteArray(response.getEntity()); 
       str  = new String(result, HTTP.UTF_8); 
      } 
     } 
     catch (UnsupportedEncodingException e) 
     { 
      e.printStackTrace(); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     return str; 
    } 
    public void setParameters(HashMap<String, String> httpRequestParameters) 
    { 
     this.mData = httpRequestParameters; 
    } 



    @Override 
    protected String doInBackground(Object... params) 
    { 
     // Ensure that we got, URL, http method and Callback 
     if (params.length != 3) 
     { 
      this.cancel(true); 
     } 
     else 
     { 
      if ((params[2] instanceof WebServiceAsyncTaskCallback)) 
      { 
       this.callbackClass = ((WebServiceAsyncTaskCallback)params[2]); 
      } 
      else 
      { 
       this.cancel(true); 
      } 
      try { 
       URL url = new URL((String)params[0]); 
      } catch (MalformedURLException e) { 
       this.callbackClass.onError("First param must be a valid URL. (" + params[0] + " given)"); 
       this.cancel(true); 
      } 
      if (!((String)params[1]).equals(POST) && !((String)params[1]).equals(GET)) 
      { 
       this.callbackClass.onError("Second parameters must be " + this.getClass().getName() + " POST or GET constant"); 
       this.cancel(true); 
      } 
     } 

     String str   = ""; 

     //IS OUR REQUEST A POST 
     if (params.length > 1) 
     { 
      if (((String)params[1]).toUpperCase().equals(WebServiceAsyncTask.POST)) 
      { 
       str = getPostResponse(((String)params[0])); 
      } 
      else if(((String)params[1]).toUpperCase().equals(WebServiceAsyncTask.GET)) //THEN GET 
      { 
       str = getGetResponse(((String)params[0])); 
      } 
     } 

     return str; 
    } 

    @Override 
    protected void onPostExecute(String result) 
    { 
     this.mData = null; 

     if (this.context != null) 
     { 
      this.publishProgress(PROGRESS_TEXT_END, PROGRESS_PERCENT_END); 
      this.progressDialog.dismiss(); 
     } 
     if (this.callbackClass != null) 
     { 
      this.callbackClass.callbackMethod(result); 
     } 
    } 

    @Override 
    protected void onPreExecute() 
    { 
     if (this.context != null) 
     { 
      this.prepareProgressDialog(); 
      this.progressDialog.show(); 
     } 
    } 

    @Override 
    protected void onProgressUpdate(String... values) { 
     if (this.context != null) 
     { 
      this.progressDialog.setMessage(values[0]); 
      this.progressDialog.setProgress(Integer.parseInt(values[1])); 
     } 
    } 


} 

/** 
* Allow to easily get the server response 
*/ 
abstract class WebServiceAsyncTaskCallback{ 
    /** 
    * Return the server response as String 
    * @param result server response as a String 
    */ 
    abstract void callbackMethod(String result); 

    /** 
    * This method is design to report simple errors for development phase. 
    * @param errMessage contains error message 
    */ 
    protected void onError(String errMessage){}; 

    ; 
} 
+0

給'Volley'庫試試吧! [Here](http://www.technotalkative.com/android-volley-library-example/)我寫了一篇文章。 –

+0

嗯,聽起來不錯,我們是否強制導入項目來使用它,或者我們可能只導入2個類? –

回答

1

您使用的AsyncTask的似乎是恰當的。正如你可能知道的..對於網絡通信,你必須使用AsyncTask或你自己的線程(擴展HandlerThread。)

如果你的應用程序經常調用AsyncTask或者同時執行AsyncTask,那麼創建你自己的線程會更有效率AsyncTask請求在API 13及更高版本中使用單個線程。)

我對您的應用程序以及它的功能不熟悉。您的用戶是否需要用於後臺網絡傳輸的對話和狀態反饋?

+0

實際上,我只是將調試過的ProgressDialog反饋(允許知道是否無法連接到服務器等等,而不必查看LogCat)。 也因爲我對我們如何在線程的活動中實現ProgressDialog感興趣。 (這裏我只是查詢一個Web服務,但是我可以在下載一個大文件的不同情況下使用相同的Class體系結構)。 錯誤報告抽象方法相同:設計用於開發階段。 –

+0

我真的不贊同。看到我的答案。 –

0

我能指出一點,因爲你沒有在一個服務中這樣做,所以當你的Activity被隱藏時,你的遠程查詢就有可能被殺死。你有,實際上,改寫IntentService ......除了你的版本會被打死的版本和框架提供,免費的,不會

IntentService,FTW

+0

哦,謝謝,我會看看intentService –