生活随笔
收集整理的這篇文章主要介紹了
异步加载图片(一)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
前言:本以為異步加載挺簡(jiǎn)單,因?yàn)榫W(wǎng)上代碼多,但真想要做好,還真不那么簡(jiǎn)單,從看代碼到弄懂再到自己寫(xiě),實(shí)在是有太多的東西需要學(xué)了,用了兩天的時(shí)間,終于弄出來(lái)了,因?yàn)橛玫交卣{(diào)函數(shù),所以理解起來(lái)可能難度有點(diǎn)大,講起來(lái)也不太好講,我盡力講的明白些,其實(shí)還是要多看代碼,自己摸索摸索,動(dòng)手寫(xiě)寫(xiě)就什么都理解了。這篇我們只講怎樣實(shí)現(xiàn)異步加載,對(duì)于滑動(dòng)時(shí)停止加載的事下篇再講。
實(shí)現(xiàn)效果:
1、異步加載圖片,在加載圖片時(shí),先加載一個(gè)默認(rèn)的圖片,然后在后臺(tái)加載圖片,加載完成后顯示出來(lái);
2、當(dāng)用戶在滑動(dòng)時(shí),停止加載圖片的線程,當(dāng)停止滑動(dòng)時(shí),看哪幾個(gè)ITEM在顯示屏內(nèi),只加載這幾個(gè),其它線程保持阻止;(下篇再講)
效果圖:
? ? ? ? ? 剛開(kāi)始加載時(shí) ? ? ? ? ? ? ? ? ? ? ? ? ?向下劃動(dòng)(新劃出來(lái)的是空白塊) ? ? ? ? ? 停劃,加載完成
????
一、XML
1、main.xml
[html] view plaincopy
<?xml?version="1.0"?encoding="utf-8"?>??<LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"??????android:orientation="vertical"??????android:layout_width="fill_parent"??????android:layout_height="fill_parent"??????>??????<ListView?android:id="@+id/list"???????????android:layout_width="fill_parent"???????????android:layout_height="fill_parent"?/>??</LinearLayout>??
2、列表子項(xiàng)XML(book_item_adapter.xml)
[html] view plaincopy
<?xml?version="1.0"?encoding="UTF-8"?>??<RelativeLayout?xmlns:android="http://schemas.android.com/apk/res/android"??????android:layout_width="fill_parent"??????android:layout_height="70.0dip"??????android:background="@drawable/item"??????android:drawingCacheQuality="high"??????android:minHeight="70.0dip"??????android:orientation="horizontal"?>????????<ImageView??????????android:id="@+id/sItemIcon"??????????android:layout_width="42.0dip"??????????android:layout_height="54.0dip"??????????android:layout_margin="10.0dip"??????????android:background="@drawable/rc_item_bg"??????????android:padding="2.0dip"??????????android:scaleType="fitXY"?/>????????<TextView??????????android:text="斗破蒼穹"??????????android:id="@+id/sItemTitle"??????????android:layout_width="fill_parent"??????????android:layout_height="30.0dip"??????????android:layout_alignTop="@+id/sItemIcon"??????????android:layout_toRightOf="@+id/sItemIcon"??????????android:gravity="center_vertical"??????????android:singleLine="true"??????????android:textColor="#ffffff"??????????android:textSize="18.0sp"?/>??</RelativeLayout>??
二、JAVA代碼
1、主頁(yè)面代碼(AsyncListImage.java)
[java] view plaincopy
package?cn.wangmeng.test;????import?java.util.ArrayList;??import?java.util.List;????import?android.app.Activity;??import?android.os.Bundle;??import?android.widget.ListView;????public?class?AsyncListImage?extends?Activity?{??????private?ListView?list;??????@Override??????public?void?onCreate(Bundle?savedInstanceState)?{??????????super.onCreate(savedInstanceState);??????????setContentView(R.layout.main);??????????list=(ListView)findViewById(R.id.list);??????????List<ImageAndText>?dataArray=new?ArrayList<ImageAndText>();??????????for?(int?i?=?0;?i?<?100;?i++)?{???????????????ImageAndText?test=new?ImageAndText("http://www.wangmeng.cn/images/logo.gif",?"test");???????????????ImageAndText?test1=new?ImageAndText("http://www.pfwx.com/files/article/image/0/54/54s.jpg",?"test1");???????????????ImageAndText?test2=new?ImageAndText("http://www.pfwx.com/files/article/image/0/4/4s.jpg","test2");???????????????ImageAndText?test3=new?ImageAndText("http://www.pfwx.com/files/article/image/9/9760/9760s.jpg","test3");???????????????ImageAndText?test4=new?ImageAndText("http://www.pfwx.com/files/article/image/3/3382/3382s.jpg","test4");???????????????ImageAndText?test5=new?ImageAndText("http://www.pfwx.com/files/article/image/3/3237/3237s.jpg","test5");???????????????dataArray.add(test);???????????????dataArray.add(test1);???????????????dataArray.add(test2);?????????????????dataArray.add(test3);?????????????????dataArray.add(test4);?????????????????dataArray.add(test5);???????????????????????????}???????????????????ImageAndTextListAdapter?adapter=new?ImageAndTextListAdapter(this,?dataArray,?list);??????????list.setAdapter(adapter);????????????????}??}??
2、ImageAndText.java
[java] view plaincopy
package?cn.wangmeng.test;????public?class?ImageAndText?{??????????private?String?imageUrl;??????????private?String?text;????????????public?ImageAndText(String?imageUrl,?String?text)?{??????????????this.imageUrl?=?imageUrl;??????????????this.text?=?text;??????????}??????????public?String?getImageUrl()?{??????????????return?imageUrl;??????????}??????????public?String?getText()?{??????????????return?text;??????????}??}??
上面兩個(gè)代碼一塊講
1、ImageAndText類(lèi)是用來(lái)存儲(chǔ)要與XML綁定的圖片地址和名字地址的。
2、將所有的地址都放在一個(gè)List里面(dataArray),然后將其傳入ImageAndTextListAdapter()函數(shù)中;可見(jiàn)這個(gè)ImageAndTextListAdapter()函數(shù)是根據(jù)傳進(jìn)去的dataArray生成對(duì)應(yīng)的Adapter的
3、然后將ImageAndTextListAdapter()返回的Adapter與listView綁定
3、ImageAndTextListAdapter.java
這是重寫(xiě)于baseAdapter的類(lèi),由于重寫(xiě)于baseAdapter,所以有幾個(gè)必須重寫(xiě)的函數(shù),getCount()、getItem()、getItemId()、getView(),我們先把總體代碼寫(xiě)出來(lái),只講一個(gè)getView()函數(shù),其實(shí)函數(shù)就不講了,先著重說(shuō)下getView()函數(shù)在什么時(shí)候被系統(tǒng)調(diào)用:
getView()函數(shù)在什么時(shí)候被系統(tǒng)調(diào)用:
注意一點(diǎn)是Android系統(tǒng)在顯示列表時(shí),并不是把所有代表都顯示出來(lái),讓你隨便劃,劃到哪是哪;而是根據(jù)當(dāng)前的在劃到的ITEM,調(diào)用當(dāng)前ITEM的getView()來(lái)顯示它。
全部代碼:
[java] view plaincopy
package?cn.wangmeng.test;????import?java.util.ArrayList;??import?java.util.List;????import?cn.wangmeng.test.AsyncImageLoader.ImageCallback;????import?android.app.Activity;??import?android.graphics.drawable.Drawable;??import?android.util.Log;??import?android.view.LayoutInflater;??import?android.view.View;??import?android.view.ViewGroup;??import?android.widget.ArrayAdapter;??import?android.widget.BaseAdapter;??import?android.widget.ImageView;??import?android.widget.ListView;??import?android.widget.TextView;????public?class?ImageAndTextListAdapter?extends?BaseAdapter?{????????????private?LayoutInflater?inflater;??????????private?ListView?listView;??????????private?AsyncImageLoader?asyncImageLoader;????????????private?List<ImageAndText>?dataArray=new?ArrayList<ImageAndText>();????????????public?ImageAndTextListAdapter(Activity?activity,?List<ImageAndText>?imageAndTexts,?ListView?listView)?{????????????????this.listView?=?listView;??????????????asyncImageLoader?=?new?AsyncImageLoader();??????????????inflater?=?activity.getLayoutInflater();??????????????dataArray=imageAndTexts;??????????}????????????????????@Override??????????public?int?getCount()?{????????????????????????????return?dataArray.size();??????????}??????????@Override??????????public?Object?getItem(int?position)?{????????????????????????????if(position?>=?getCount()){??????????????????return?null;??????????????}??????????????return?dataArray.get(position);??????????}??????????@Override??????????public?long?getItemId(int?position)?{????????????????????????????return?position;??????????}??????????????????????public?View?getView(int?position,?View?convertView,?ViewGroup?parent)?{??????????????if?(convertView?==?null)?{???????????????????convertView?=?inflater.inflate(R.layout.book_item_adapter,?null);??????????????}??????????????convertView.setTag(position);????????????????????????????ImageAndText?imageAndText?=?(ImageAndText)?getItem(position);??????????????String?imageUrl?=?imageAndText.getImageUrl();????????????????????????????TextView?textView?=??(TextView)?convertView.findViewById(R.id.sItemTitle);?????????????????????????????textView.setText(imageAndText.getText());??????????????ImageView?iv?=?(ImageView)?convertView.findViewById(R.id.sItemIcon);??????????????iv.setBackgroundResource(R.drawable.rc_item_bg);??????????????????????????????????????????????????????????????asyncImageLoader.loadDrawable(position,imageUrl,?new?ImageCallback()?{??????????????????@Override??????????????????public?void?onImageLoad(Integer?pos,?Drawable?drawable)?{??????????????????????View?view?=?listView.findViewWithTag(pos);??????????????????????if(view?!=?null){??????????????????????????ImageView?iv?=?(ImageView)?view.findViewById(R.id.sItemIcon);??????????????????????????iv.setBackgroundDrawable(drawable);??????????????????????}??????????????????}????????????????????????????????????@Override??????????????????public?void?onError(Integer?pos)?{??????????????????????View?view?=?listView.findViewWithTag(pos);??????????????????????if(view?!=?null){??????????????????????????ImageView?iv?=?(ImageView)?view.findViewById(R.id.sItemIcon);??????????????????????????iv.setBackgroundResource(R.drawable.rc_item_bg);??????????????????????}??????????????????}????????????????????????????????});??????????????return?convertView;??????????}??}??
我們著重看getView()函數(shù)
1、看這段:
[java] view plaincopy
if?(convertView?==?null)?{???????convertView?=?inflater.inflate(R.layout.book_item_adapter,?null);??}??convertView.setTag(position);????ImageAndText?imageAndText?=?(ImageAndText)?getItem(position);??String?imageUrl?=?imageAndText.getImageUrl();????TextView?textView?=??(TextView)?convertView.findViewById(R.id.sItemTitle);?????textView.setText(imageAndText.getText());??ImageView?iv?=?(ImageView)?convertView.findViewById(R.id.sItemIcon);??iv.setBackgroundResource(R.drawable.rc_item_bg);??
這段代碼沒(méi)什么特別的就是將前面dataArray的信息與XML的元素項(xiàng)對(duì)應(yīng)起來(lái),并綁定,最關(guān)鍵的是下面這段,下面這個(gè)方法才是實(shí)現(xiàn)異步加載圖片的關(guān)鍵:
[java] view plaincopy
asyncImageLoader.loadDrawable(position,imageUrl,?new?ImageCallback()?{??????@Override??????public?void?onImageLoad(Integer?pos,?Drawable?drawable)?{??????????View?view?=?listView.findViewWithTag(pos);??????????if(view?!=?null){??????????????ImageView?iv?=?(ImageView)?view.findViewById(R.id.sItemIcon);??????????????iv.setBackgroundDrawable(drawable);??????????}??????}????????????@Override??????public?void?onError(Integer?pos)?{??????????View?view?=?listView.findViewWithTag(pos);??????????if(view?!=?null){??????????????ImageView?iv?=?(ImageView)?view.findViewById(R.id.sItemIcon);??????????????iv.setBackgroundResource(R.drawable.rc_item_bg);??????????}??????}????????});??
這段代碼的奇特之處在于,利用AsyncImageLoader類(lèi)的實(shí)例(asyncImageLoader),調(diào)用方法loadDrawable()方法,就實(shí)現(xiàn)了加載后圖像的綁定;好神奇,仔細(xì)看他是怎么做到的。這里先注意的有兩點(diǎn):
(1)、傳進(jìn)去的參數(shù),當(dāng)前項(xiàng)的位置(position),當(dāng)前圖片的URL(imageUrl),一個(gè)名稱為ImageCallback()接口函數(shù);
(2)、ImageCallback()接口函數(shù)里的兩個(gè)被重寫(xiě)的函數(shù)onImageLoad()和onError()
3、AsyncImageLoader.java
從上面的講解也應(yīng)該能猜到這個(gè)類(lèi),主要的功能就是加載圖片,然后成功后更新UI;
先看全部代碼,然后再逐步講
[java] view plaincopy
package?cn.wangmeng.test;????import?java.io.IOException;??import?java.io.InputStream;??import?java.lang.ref.SoftReference;??import?java.net.URL;??import?java.util.HashMap;????import?android.graphics.drawable.Drawable;??import?android.os.Handler;????public?class?AsyncImageLoader?{??????final?Handler?handler?=?new?Handler();??????private?HashMap<String,?SoftReference<Drawable>>?imageCache;??????public?AsyncImageLoader()?{??????????imageCache?=?new?HashMap<String,?SoftReference<Drawable>>();??????}??????????????????public?interface?ImageCallback?{??????????public?void?onImageLoad(Integer?t,?Drawable?drawable);??????????public?void?onError(Integer?t);??????}????????public?Drawable?loadDrawable(final?Integer?pos,?final?String?imageUrl,???????????????final?ImageCallback?imageCallback)?{??????????new?Thread()?{??????????????@Override??????????????public?void?run()?{????????????????????????????????????LoadImg(pos,?imageUrl,?imageCallback);????????????????}??????????}.start();??????????return?null;??????}????????public?void?LoadImg(final?Integer?pos,?final?String?imageUrl,??????????????final?ImageCallback?imageCallback)?{??????????????????????????????if?(imageCache.containsKey(imageUrl))?{??????????????SoftReference<Drawable>?softReference?=?imageCache.get(imageUrl);??????????????final?Drawable?drawable?=?softReference.get();??????????????if?(drawable?!=?null)?{??????????????????handler.post(new?Runnable()?{??????????????????????@Override??????????????????????public?void?run()?{??????????????????????????imageCallback.onImageLoad(pos,?drawable);??????????????????????}??????????????????});??????????????????return;??????????????}??????????}????????????????????try?{??????????????final?Drawable?drawable?=?loadImageFromUrl(imageUrl);??????????????if?(drawable?!=?null)?{??????????????????imageCache.put(imageUrl,?new?SoftReference<Drawable>(drawable));??????????????}??????????????handler.post(new?Runnable()?{??????????????????@Override??????????????????public?void?run()?{??????????????????????????imageCallback.onImageLoad(pos,?drawable);??????????????????}??????????????});??????????}?catch?(IOException?e)?{??????????????handler.post(new?Runnable()?{??????????????????@Override??????????????????public?void?run()?{??????????????????????imageCallback.onError(pos);??????????????????}??????????????});??????????????e.printStackTrace();??????????}????????}??????????????public?static?Drawable?loadImageFromUrl(String?url)?throws?IOException?{??????????URL?m;??????????InputStream?i?=?null;??????????m?=?new?URL(url);??????????i?=?(InputStream)?m.getContent();??????????Drawable?d?=?Drawable.createFromStream(i,?"src");??????????return?d;??????}????}??
分別講解
1、先看這段代碼
[java] view plaincopy
??public?interface?ImageCallback?{??????public?void?onImageLoad(Integer?t,?Drawable?drawable);??????public?void?onError(Integer?t);??}????public?Drawable?loadDrawable(final?Integer?pos,?final?String?imageUrl,???????????final?ImageCallback?imageCallback)?{??????new?Thread()?{??????????@Override??????????public?void?run()?{????????????????????????????LoadImg(pos,?imageUrl,?imageCallback);????????????}??????}.start();??????return?null;??}??
(1)首先注意,剛才我們調(diào)用的loadDrawable()函數(shù),里面初始化并運(yùn)行了一個(gè)線程,而這個(gè)線程的里面只有一個(gè)函數(shù)LoadImg(),對(duì)于這個(gè)函數(shù)下面我們具體講,它的主要功能就是加載圖片,然后更新UI
(2)上面也看出了ImageCallback是一個(gè)接口,而里面的兩個(gè)函數(shù)onImageLoad()和onError()在這里是沒(méi)有具體實(shí)現(xiàn)的,那在哪里實(shí)現(xiàn)呢,當(dāng)然是我們上面的ImageAndTextListAdapter.java里面了,等下我們具體會(huì)再講。
再往下看
[java] view plaincopy
??????public?static?Drawable?loadImageFromUrl(String?url)?throws?IOException?{??????????URL?m;??????????InputStream?i?=?null;??????????m?=?new?URL(url);??????????i?=?(InputStream)?m.getContent();??????????Drawable?d?=?Drawable.createFromStream(i,?"src");??????????return?d;??????}????????public?void?LoadImg(final?Integer?pos,?final?String?imageUrl,??????????final?ImageCallback?imageCallback)?{??????????????????if?(imageCache.containsKey(imageUrl))?{??????????SoftReference<Drawable>?softReference?=?imageCache.get(imageUrl);??????????final?Drawable?drawable?=?softReference.get();??????????if?(drawable?!=?null)?{??????????????handler.post(new?Runnable()?{??????????????????@Override??????????????????public?void?run()?{??????????????????????imageCallback.onImageLoad(pos,?drawable);??????????????????}??????????????});??????????????return;??????????}??????}????????????try?{??????????final?Drawable?drawable?=?loadImageFromUrl(imageUrl);??????????if?(drawable?!=?null)?{??????????????imageCache.put(imageUrl,?new?SoftReference<Drawable>(drawable));??????????}??????????handler.post(new?Runnable()?{??????????????@Override??????????????public?void?run()?{??????????????????????imageCallback.onImageLoad(pos,?drawable);??????????????}??????????});??????}?catch?(IOException?e)?{??????????handler.post(new?Runnable()?{??????????????@Override??????????????public?void?run()?{??????????????????imageCallback.onError(pos);??????????????}??????????});??????????e.printStackTrace();??????}????}??
(1)、loadImageFromUrl()函數(shù),就是根據(jù)URL到網(wǎng)上加載圖片,然后返回圖片流Drawable類(lèi)型變量
(2)、對(duì)于LoadImg()我們?cè)俨鹨幌?#xff0c;先看如何在緩存中加載
[java] view plaincopy
if?(imageCache.containsKey(imageUrl))?{??????SoftReference<Drawable>?softReference?=?imageCache.get(imageUrl);??????final?Drawable?drawable?=?softReference.get();??????if?(drawable?!=?null)?{??????????handler.post(new?Runnable()?{??????????????@Override??????????????public?void?run()?{??????????????????imageCallback.onImageLoad(pos,?drawable);??????????????}??????????});??????????return;??????}??}??
注意:
1、在這里就已經(jīng)得到了圖像
[java] view plaincopy
SoftReference<Drawable>?softReference?=?imageCache.get(imageUrl);??final?Drawable?drawable?=?softReference.get();??
2、得到圖像之后就到了這段代碼:
[java] view plaincopy
if?(drawable?!=?null)?{??????handler.post(new?Runnable()?{??????????@Override??????????public?void?run()?{??????????????imageCallback.onImageLoad(pos,?drawable);??????????}??????});??????return;??}??
當(dāng)我們得到圖像之后,調(diào)用imageCallback.onImageLoad(pos, drawable);來(lái)更新UI,由于我們?cè)倩貋?lái)看看ImageAndTextListAdapter.java中的代碼
[java] view plaincopy
asyncImageLoader.loadDrawable(position,imageUrl,?new?ImageCallback()?{??????@Override??????public?void?onImageLoad(Integer?pos,?Drawable?drawable)?{??????????View?view?=?listView.findViewWithTag(pos);??????????if(view?!=?null){??????????????ImageView?iv?=?(ImageView)?view.findViewById(R.id.sItemIcon);??????????????iv.setBackgroundDrawable(drawable);??????????}??????}????????});??
看到了吧,就是把得到的drawable與加載到UI中!!!!這就實(shí)現(xiàn)了回調(diào)
OK,就到這吧,OnError()的原理一樣,只不過(guò)是對(duì)程序沒(méi)有加載到圖片時(shí)應(yīng)該怎么處理,其實(shí)就是當(dāng)沒(méi)有加載到圖片時(shí)就是默認(rèn)圖片代替。
下面給出源碼:http://download.csdn.net/detail/harvic880925/6802241(不要分,僅供分享)
請(qǐng)大家尊重作者板權(quán),轉(zhuǎn)載請(qǐng)標(biāo)明出處:
http://blog.csdn.net/harvic880925/article/details/17766027?
,謝謝!
總結(jié)
以上是生活随笔為你收集整理的异步加载图片(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。