Android網路編程 HttpUrlConnection HttpClient AsyncTask
1,HttpUrlConnection
一個UrlConnection常用來通過網路發送和擷取資料,資料可以使任何類型任何長度,HttpUrlConnection通常用於發送和接收長度未知的流資料;
建立HttpURLConnection:通過調用Url.openConnection()並將其類型轉換為HttpUrlConnection
建立Request:要包含最基本的Url,你可以佈建要求頭部(請求資料類型,長度等)
佈建要求主體(body):這不是必須的,如果需要設定,確保setOutput(true);
讀取Response:返迴響應,頭部包含資料類型,長度等資料,可以通過getInputStream()讀取響應資料的主體(body),如果沒有Response沒有body,則返回一個Empty Stream
中斷連線:調用HttpUrlConnection的disconnect()方法
使用HttpUrlConnection的一個簡單樣本:從遠程擷取圖片並顯示在ImageView中
ImageView imageView=(ImageView).findViewById(R.id.imageview);URL url=new URL(http://www.jycoder.com/json/movies/1.jpg); HttpUrlConnection conn= (HttpUrlConnection) url.openConnection();conn.connect();try{ InputStream in=conn.getInputStream(); //將擷取到的圖片顯示在ImageView中 Bitmap bitmap=BitmapFactory.decodeStream(in); imageView.setImageBitmap(BitmapFactory.decode(is)); } finally{ conn.disconnect(); }
上面就是HttpUrlConnection的基本用法,還有些需要掌握的主題:
Http Response錯誤:有時候響應錯誤或者異常,直接getInputStream()就會拋出異常,我們可以通過getErrorStream();讀取Response錯誤資訊,getHeaderFields()讀取回應標頭部;
Post Content:發送資料到伺服器,首先需要setOutput(true);為了效能,如果你知道你所Post內容的大小,你可以使用setFixedLengthStreamingMode(int),如果不知道,可以使用setChunkedStreamingMode(int);
HTTP Method:可以通過setRequestMethod(String)設定
Cookie和Cache:HttpUrlConnection擁有CookieManager和CookieHandler方法來設定Cookie,對於Cache提供了HttpResponseCache類;關於這部分參考資料:HttpUrlConnection
HttpResponseCache
2,HttpClient
Android 官方在API 22之後已經棄用,盡量使用HttpUrlConnection
3,AsyncTask
AsyncTask是實現非同步作業的一種機制,我們常常需要更新UI,但主線程不能執行耗時操作,否則會引發錯誤;AsyncTask用於執行後台操作,無需手動處理線程的建立和執行;它常用來處理一些短時操作,如果長時間操作考慮使用Service
AsyncTask的使用:
建立一個Task:我們需要建立一個Task繼承自AsyncTask,
AsyncTask中需要三個參數Params,Progress,Result:
Params 代表task執行時需要傳給的參數:new MyTask.execute(Params); Progress 代表任務內需要傳遞的任務進度,與之相關的方法是publisProgress()和onUpdateProgress() Result 代表最終Task執行完我們所得到的結果 我們還需要覆寫AsyncTask中的四個方法:
onPreExecute() Task執行前調用,在主線程(UI線程)中運行,進行諸如建立最初的進度條視圖之類的工作 doInBackground() 後台線程中運行,擷取網路資料等耗時操作都在這裡進行 onUpdateProgress() 主線程中運行,用於更新進度,在doInBackground()方法中調用publishProgress()方法時回調。 onPostExecute() 主線程中運行,當task完成時調用,
Tips:可以看到AsyncTask中的四個方法只有doInBackground()實在後台線程中啟動並執行,因此在它裡面執行一些耗時操作,而其它方法運行在UI線程,執行更新UI視圖等操作。
在主線程中執行Task:必須在主線程中執行個體化和執行AsyncTask,而且每個AsyncTask只執行一次
取消一個Task:AsyncTask可以在任何時候通過調用cancel(true)取消。
綜合以上我們來做個練習:
建立項目:
UseAsyncTask
在Manifest.xml中添加連網許可權
建立布局,我們這裡用來顯示一張電影圖片,
完成
MainActivity
public class MainActivity extends ActionBarActivity { private ImageView imageView; //圖片地址 private final String url=http://www.jycoder.com/json/movies/2.jpg; //顯示進度 private ProgressDialog pDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //用來顯示進度 pDialog=new ProgressDialog(this); pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pDialog.setMessage(Loading...); pDialog.setMax(100); imageView= (ImageView) findViewById(R.id.movie_image); //執行Task new ImageDownloadTask().execute(url); } public class ImageDownloadTask extends AsyncTask{ @Override protected void onPreExecute() { super.onPreExecute(); pDialog.show(); } @Override protected Bitmap doInBackground(String... urls) { HttpURLConnection connection = null; Bitmap bitmap=null; try { URL url=new URL(urls[0]); connection= (HttpURLConnection) url.openConnection(); InputStream in= new BufferedInputStream(connection.getInputStream()); bitmap= BitmapFactory.decodeStream(in); //擷取檔案流大小,用於更新進度 int length=connection.getContentLength(); int len=0,total_length=0,value=0; byte[] data=new byte[1024]; while((len = in.read(data)) != -1){ total_length += len; value = (int)((total_length/(float)length)*100); //調用update函數,更新進度 publishProgress(value); } } catch (IOException e) { e.printStackTrace(); }finally { if (connection!=null) connection.disconnect(); } return bitmap; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); pDialog.setProgress(values[0]); } @Override protected void onPostExecute(Bitmap bitmap) { if(pDialog!=null) pDialog.dismiss(); pDialog = null; //將Bitmap填充進Imageview imageView.setImageBitmap(bitmap); } }}
總結:
這部分內容很簡單吧~,其實這部分難的就是我們需要理解UI線程,以及瞭解AsyncTask與Service的適用情境。