Android網路程式設計 HttpUrlConnection HttpClient AsyncTask
前面幾篇文章介紹了Android中常用的http框架:volley,所謂框架者無非就是對我們所需的一系列操作進行了封裝,簡化了我們的工作。
但萬變不離其宗,我們還是需要掌握Android原生的網路操作類,所以這篇文章主要介紹這兩個類,
HTTPUrlConnection
HTTPClient
,以及常需要用到的AsyncTask
.
1,HttpUrlConnection
一個UrlConnection常用來通過網路傳送和獲取資料,資料可以使任何型別任何長度,HttpUrlConnection通常用於傳送和接收長度未知的流資料;
- 建立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檢視等操作。
- AsyncTask中需要三個引數Params,Progress,Result:
- 在主執行緒中執行Task:必須在主執行緒中例項化和執行AsyncTask,而且每個AsyncTask只執行一次
- 取消一個Task:AsyncTask可以在任何時候通過呼叫cancel(true)取消。
綜合以上我們來做個練習:
- 新建專案:
UseAsyncTask
在
Manifest.xml
中新增聯網許可權建立佈局,我們這裡用來顯示一張電影圖片,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:text="豆瓣電影Top10"
android:background="#1C9439"
android:textSize="24sp"
android:textColor="#fff"
android:layout_marginTop="5dp"
android:layout_marginBottom="10dp"
android:gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/movie_image"
android:layout_gravity="center"
android:background="#ffcc"
android:layout_margin="3dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
- 完成
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<String,Integer,Bitmap>{
@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的適用場景。