標籤:getresponsecode 阻塞 asynctask
在實際應用中經常會遇到比較耗時任務的處理,比如網路連接,資料庫操作等情況時,如果這些操作都是放在主線程(UI線程)中,則會造成UI的假死現象,Android中可以使用AsyncTask和Handler兩種非同步方式來解決這種問題。
AsyncTask(非同步任務處理)在使用AsyncTask時處理類需要繼承AsyncTask,提供三個泛型參數,並且重載AsyncTask的四個方法(至少重載一個)。
An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.
三個泛型參數1.Param 任務執行器需要的資料類型
2.Progress 後台計算中使用的進度單位元據類型
3.Result 後台計算返回結果的資料類型
在設定參數時通常是這樣的:String... params,這表示方法可以有0個或多個此型別參數;有時參數可以設定為不使用,用Void...即可。
四個方法1.onPreExecute() 執行預先處理,它運行於UI線程,可以為背景工作做一些準備工作,比如繪製一個進度條控制項。
2.doInBackground(Params...) 後台進程執行的具體計算在這裡實現,doInBackground(Params...)是AsyncTask的關鍵,此方法必須重載。在這個方法內可以使用publishProgress(Progress...)改變當前的進度值。
3.onProgressUpdate(Progress...) 運行於UI線程。如果在doInBackground(Params...) 中使用了publishProgress(Progress...),就會觸發這個方法。在這裡可以對進度條控制項根據進度值做出具體的響應。
4.onPostExecute(Result) 運行於UI線程,可以對背景工作的結果做出處理,結果就是doInBackground(Params...)的返回值。此方法也要經常重載,如果Result為null表明背景工作沒有完成(被取消或者出現異常)。
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } }
執行代碼:
new DownloadFilesTask().execute(url1, url2, url3);
將android的POST方法放入doInBackground(URL... url)
// Post方式請求public static void requestByPost() throws Throwable {String path = "https://reg.163.com/logins.jsp";// 請求的參數轉換為byte數組String params = "id=" + URLEncoder.encode("helloworld", "UTF-8")+ "&pwd=" + URLEncoder.encode("android", "UTF-8");byte[] postData = params.getBytes();// 建立一個URL對象URL url = new URL(path);// 開啟一個HttpURLConnection串連HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();// 設定連線逾時時間urlConn.setConnectTimeout(5 * 1000);// Post請求必須設定允許輸出urlConn.setDoOutput(true);// Post請求不能使用緩衝urlConn.setUseCaches(false);// 設定為Post請求urlConn.setRequestMethod("POST");urlConn.setInstanceFollowRedirects(true);// 配置請求Content-TypeurlConn.setRequestProperty("Content-Type","application/x-www-form-urlencode");// 開始串連urlConn.connect();// 發送請求參數DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());dos.write(postData);dos.flush();dos.close();// 判斷請求是否成功if (urlConn.getResponseCode() == HTTP_200) {// 擷取返回的資料byte[] data = readStream(urlConn.getInputStream());Log.i(TAG_POST, "Post請求方式成功,返回資料如下:");Log.i(TAG_POST, new String(data, "UTF-8"));} else {Log.i(TAG_POST, "Post方式請求失敗");}}
//***************************************************分割*************************************************************
在使用if(HTTP_200 == urlConn.getResponseCode())我在考慮getResponseCode()是不是一個阻塞方法(這裡一定是,不然網路會一直失敗),如果是阻塞那麼會維持多久,多久後會給你網路代碼編號?
這就很奇怪了,在URLConnection.java並沒有表現出來是阻塞方法,但是其中httpURLConnect.java和URLConnection.java都是抽象類別(abstract類)當我們調用抽象類別的方法,經過查閱資料stackoverflow,發現具體的實現機制在底層sun.net.www.protocol.http.HttpURLConnection.。
這裡我猜想java.net.HttpURLConnection和sun.net.www.protocol.http.HttpURLConnection存在繼承關係,java.net.HttpURLConnection繼承了java.net.URLConnection.java抽象方法,同時java.net.HttpURLConnection自己也是抽象類別,一些實體實現對應到sun.net.www.protocol.http.HttpURLConnection中(這裡sun.net.www.protocol.http.HttpURLConnection繼承java.net.HttpURLConnection),在我們使用對應方法的時候就會調用實現實體(也可以說是重寫後的方法)。
getResponseCode()的阻塞實現也就找到了,在getInputStream()中。
android非同步請求asyncTask使用—分析getResponseCode()阻塞