情境
如果你想從網路上下載圖片, 該怎麼寫呢?
以下可能需要參考的觀念:
- 如何使用Thread和Handler
- 一些Http request的觀念。
程式碼說明
首先在XML先定義一個ImageView跟ProgressBar
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<RelativeLayout
android:id="@+id/img_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="@+id/progress_bar" />
<ImageView
android:visibility="gone"
android:layout_width="200dp"
android:layout_height="200dp"
android:id="@+id/imageView"/>
</RelativeLayout>
<Button
android:layout_below="@id/img_layout"
android:id="@+id/download_btn"
android:text="download img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
這樣一開始就讓使用者知道目前正在讀取, 不至於以為程式當機將程式關閉。
接著宣告一個類別叫作DownloadWebPicture
public class DownloadWebPicture {}
然後在裡面加入下面的程式碼
public class DownloadWebPicture {
private Bitmap bmp;
public Bitmap getImg(){
return bmp;
}
public void handleWebPic(final String url, final Handler handler){
new Thread(new Runnable(){
@Override
public void run() {
bmp = getUrlPic(url);
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
}
}).start();
}
public synchronized Bitmap getUrlPic(String url) {
Bitmap webImg = null;
try {
URL imgUrl = new URL(url);
HttpURLConnection httpURLConnection
= (HttpURLConnection) imgUrl.openConnection();
httpURLConnection.connect();
InputStream inputStream = httpURLConnection.getInputStream();
int length = (int) httpURLConnection.getContentLength();
int tmpLength = 512;
int readLen = 0,desPos = 0;
byte[] img = new byte[length];
byte[] tmp = new byte[tmpLength];
if (length != -1) {
while ((readLen = inputStream.read(tmp)) > 0) {
System.arraycopy(tmp, 0, img, desPos, readLen);
desPos += readLen;
}
webImg = BitmapFactory.decodeByteArray(img, 0, img.length);
if(desPos != length){
throw new IOException("Only read" + desPos +"bytes");
}
}
httpURLConnection.disconnect();
}
catch (IOException e) {
Log.e("IOException", e.toString());
}
return webImg;
}
}
這邊如果你沒有Http以及IOStream的概念, 可以把這個方法當成一個黑盒子,
只需要傳入圖片網址, 就會回傳一個Bitmap的物件。
這個方法大致解釋一下, 網址用URL打開一個連線, 然後從這個連線取得一個串流,
之後先取得圖片的大小, 之後用一個陣列來裝圖片的串流,
再利用BitmapFactory的方法轉成Bitmap的物件。
接著在宣告一個方法handleWebPic
public void handleWebPic(final String url, final Handler handler){
new Thread(new Runnable(){
@Override
public void run() {
bmp = getUrlPic(url);
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
}
}).start();
}
這個方法傳入圖片位址, 以及一個Handler,
Handler是用來跑Thread的時候, 送出一個訊息給Main Thread知道我下載完成。
然後寫一個方法可以取得下載完成的圖片
public Bitmap getImg(){
return bmp;
}
接下來到Activity這邊
private DownloadWebPicture loadPic;
private Handler mHandler;
private ProgressBar progressBar;
private ImageView imageView;
private final static String url = "https://dl.dropboxusercontent.com/u/24682760/Android_AS/DownloadImageDemo/monkey.png";
定義一些變數, 並且在onCreate內初始化這些變數
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
progressBar = (ProgressBar)findViewById(R.id.progress_bar);
imageView = (ImageView)findViewById(R.id.imageView);
loadPic = new DownloadWebPicture();
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case 1:
progressBar.setVisibility(View.GONE);
imageView.setImageBitmap(loadPic.getImg());
break;
}
super.handleMessage(msg);
}
};
loadPic.handleWebPic(url, mHandler);
}
下載這張圖
從程式中可以看到, 建立一個Handler來處理Thread丟回來的變數,
當Thread通知Handler說處理好的時候, 我們就將ProgressBar隱藏起來,
然後將下載完的圖片丟進ImageView就完成了這支程式。
按下button
開始loading
讀取完畢就顯示圖片
記得加權限
<uses-permission android:name="android.permission.INTERNET" />