好像很長時間沒有寫技術文章了,正好最近整理了一下前陣子做的android開發,在這裡記錄一下。這是一個簡單的應用-下載指定URL的圖片並顯示。
說實在的這個應用沒有什麼特殊的地方,規模很小,用到的技術也很普通,但不失為一個很好的練手題材。既然是一個android的應用,那麼裡面多少涉及到了一些android開發的技術點,具體如下:
1. 介面-ImageSwitcher, ImageView, Gallery, Dialog, ProcessBar等等控制項
2. 網路訪問- HttpClient, HttpEntity, HttpGet, HttpResponse等
3. 圖片檔案處理- Bitmap, BitmapFactory, ByteArrayOutputStream等
4. Java -如WeakReference等
5. Unit Test - ActivityInstrumentationTestCase2, LargeTest, KeyEvent等
因為沒有準備去儲存圖片檔案到外存,所以在例子中不涉及到資料庫和磁碟檔案讀寫的內容。下面我們按照軟體工程的做法,先進行一下需求分析的。
其實不複雜,稍微思考一下我們就能得到以下的基本需求:
1. 輸入URL
2. 下載圖片
3. 顯示圖片
如果要進一步的最佳化這個應用,我們還需要做以下工作:
4. 良好的互動介面 - 如URL輸入方式,錯誤處理,圖片展示等等
5. 效能最佳化 - 記憶體使用量率,網路延遲等
好了,需求確定下來以後,我們就要進入開發階段了。實際上按照敏捷的開發方式來做,我們還要進一步的拆分需求。但自己做就不那麼教條了^_^。根據TDD實踐原則,那麼我先來寫一些測試。因為使用Eclipse來建立的android項目(如何搭建開發環境請上網搜,很多啦)。你可以在構建工程時同時構建測試工程,假設工程名為PicShow
這步完成後,我們會得到2個工程PicShow, PicShowTest。下面向PicShow的工程中添加代碼了,在這之前我要給PicShowTest工程加入一些測試代碼,
因為將來會有一個類叫PicShow用於顯示下載的圖片,所以我在setUp方法中這寫:
@Overrideprotected void setUp() throws Exception {super.setUp();final PicShow a = getActivity();assertNotNull(a);}
當你寫完這段代碼,編譯一定不能通過,因為這個時候PicShow類還沒定義, ^_^。那麼我們可以藉助Eclipse神奇的快速修正功能(ctrl+1)來建立一個類。然後建立一個TextBox用於輸入URL, 一個Button處理點擊事件。那在android裡你有兩種選擇來建立控制項,一是用代碼產生一個執行個體,二是用layout檔案。通常做法是選擇後者(可以少寫不少代碼哦^_^),最後還需要一個imageView對象來顯示圖片。到這裡就需要添加真正的測試代碼了:
@LargeTest
public void testDownloadImage() throws Exception {
sendKeys(KeyEvent.KEYCODE_ENTER);
SystemClock.sleep(5000);
SimpleImageViewListAdapter adapter = (SimpleImageViewListAdapter)ga.getAdapter();
ImageView iv = (ImageView)adapter.getItem(0);
assertTrue( iv.getDrawable() != null);
}
在android的測試裡面有幾個annotation: @SmallTest, @MediumTest, @LargeTest。這些annotation有什麼區別呢?
Feature |
Small |
Medium |
Large |
Network access |
No |
localhost only |
Yes |
Database |
No |
Yes |
Yes |
File system access |
No |
Yes |
Yes |
Use external systems |
No |
Discouraged |
Yes |
Multiple threads |
No |
Yes |
Yes |
Sleep statements |
No |
Yes |
Yes |
System properties |
No |
Yes |
Yes |
Time limit (seconds) |
60 |
300 |
900+ |
主要是跟測試的內容有關係,我們在測試中要訪問網路所以需要使用@LargeTest標誌。接下來我們寫一段下載圖片的代碼給按鈕的Click事件調用:
public Bitmap loadImageFromUrl(String url) throws Exception {
final DefaultHttpClient client = new DefaultHttpClient();
final HttpGet getRequest = new HttpGet(url);
HttpResponse response = client.execute(getRequest);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.e("PicShow", "Request URL failed, error code =" + statusCode);
}
HttpEntity entity = response.getEntity();
if (entity == null) {
Log.e("PicShow", "HttpEntity is null");
}
InputStream is = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
is = entity.getContent();
byte[] buf = new byte[1024];
int readBytes = -1;
while ((readBytes = is.read(buf)) != -1) {
baos.write(buf, 0, readBytes);
}
} finally {
if (baos != null) {
baos.close();
}
if (is != null) {
is.close();
}
}
byte[] imageArray = baos.toByteArray();
return BitmapFactory.decodeByteArray(
imageArray, 0, imageArray.length);
}
這樣我們一個簡單的圖片下載應用就搞定的。完整代碼就在這裡