編輯:Android開發實例
ListView在Android應用裡扮演非常重要的角色,但很多開發者在使用ListView時都遇到過不少麻煩。一個常見的問題是:列表中要顯示一系列記錄,每條記錄帶有一張縮略圖(產品照片、用戶頭像等等),而這個縮略圖是通過一個遠程URL地址來標識的。這樣的應用場景該如何實現呢?
為了避免下載圖片帶來的延遲,所有遠程圖片都應該使用異步方式加載,即使用單獨的線程下載圖片,待圖片下載完畢後顯示在ImageView裡。Android裡可以像普通Java一樣啟動新線程,但當這個線程要更新界面時,必須使用Handler來請求,否則會為應用程序帶來潛在危害。
為了將復雜的邏輯分離,我們單獨寫一個名為RemoteImageHelper的類來處理“異步下載圖片並更新到界面”這個問題,這個類能夠實現以下功能:
下面讓我們來看一下實現代碼:
首先需要有一個方法下載遠程圖片,這裡我們不用把圖片下載到手機上,直接返回一個InputStream類型的結果即可。如果運行時這個方法報錯,請檢查是否在AndroidManifest.xml裡添加了android.permission.INTERNET權限。
private InputStream download(String urlString) throws MalformedURLException, IOException { InputStream inputStream = (InputStream) new URL(urlString).getContent(); return inputStream; }
然後是最主要的異步加載圖片方法,“正在下載”和“下載失敗”的圖片可根據需要自己替換。代碼如下所示:
private final Map<String, Drawable> cache = new HashMap<String, Drawable>(); public void loadImage(final ImageView imageView, final String urlString, boolean useCache) { if (useCache && cache.containsKey(urlString)) { imageView.setImageDrawable(cache.get(urlString)); } //Show a "Loading" image here imageView.setImageResource(R.drawable.image_indicator); Log.d(this.getClass().getSimpleName(), "Image url:" + urlString); final Handler handler = new Handler() { @Override public void handleMessage(Message message) { imageView.setImageDrawable((Drawable) message.obj); } }; Runnable runnable = new Runnable() { public void run() { Drawable drawable = null; try { InputStream is = download(urlString); drawable = Drawable.createFromStream(is, "src"); if (drawable != null) { cache.put(urlString, drawable); } } catch (Exception e) { Log.e(this.getClass().getSimpleName(), "Image download failed", e); //Show a "download fail" image drawable = imageView.getResources().getDrawable(R.drawable.image_fail); } //Notify UI thread to show this image using Handler Message msg = handler.obtainMessage(1, drawable); handler.sendMessage(msg); } }; new Thread(runnable).start(); }
關於緩存:在這個例子裡我們使用一個內存中的HashMap作為圖片緩存,它實現簡單但當應用退出後緩存就會被清除。在實際項目裡,你可以考慮實現一個基於文件的緩存機制,即將下載的圖片保存到SD卡上,注意要定期清除長期不用的圖片以節約存儲空間。
如何使用這個類呢?下面是一個例子。請注意,為了達到更好的演示效果,代碼裡在調用loadImage()方法時第三個參數用false禁止了圖片緩存功能,在實際項目中,你很可能需要改為true來避免重復下載圖片以便提高性能。
List<MyRecord> exampleRecords; LazyImageHelper lazyImageHelper = new LazyImageHelper(); class MyAdapter extends ArrayAdapter<MyRecord> { public MyAdapter(Context context) { super(context, R.layout.record_row, R.id.lblLabel, exampleRecords); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); MyRecord record = getItem(position); TextView lblLabel = (TextView) view.findViewById(R.id.lblLabel); ImageView imageView = (ImageView) view.findViewById(R.id.img); lblLabel.setText(record.getLabel()); //For demo purpose, cache is DISABLED here. lazyImageHelper.loadImage(imageView, record.getImageUrl(), false); //To enable cache, simply use following code: //lazyImageHelper.loadImage(imageView, record.getImageUrl(), true); return view; } }
以上代碼中的MyRecord是一個簡單的POJO類,表示一個業務對象,它具有id、label和imageUrl三個屬性。你可以在完整的工程代碼中找到它。
上述示例工程編譯後的APK文件點擊這裡下載,可運行在Android 2.1或以上版本。
上述示例工程的源代碼點擊這裡下載。
Handler
android的消息處理機制
How do I do a lazy load of images in ListView
Issue 13959:Make listviews more programmer friendly
Android的允許通過添加不同種類的處理圖像效果。可以輕松地應用圖像處理技術來增加某些種類的圖像效果。這些影響可能是亮度,黑暗中,灰度轉換等Android提供了Bitm
微信平台開放後倒是挺火的,許多第三方應用都想試下,畢竟可以利用微信建立起來的關系鏈來拓展自己的應用還是挺不錯的,可以節約很多在社交方面的開銷,我最近由於實習需要也
具體代碼如下: main.xml 代碼如下:<LinearLayout xmlns:android=http://schemas.android.com/
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用