生活随笔
收集整理的這篇文章主要介紹了
异步加载图片(一)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言:本以為異步加載挺簡單,因為網上代碼多,但真想要做好,還真不那么簡單,從看代碼到弄懂再到自己寫,實在是有太多的東西需要學了,用了兩天的時間,終于弄出來了,因為用到回調函數,所以理解起來可能難度有點大,講起來也不太好講,我盡力講的明白些,其實還是要多看代碼,自己摸索摸索,動手寫寫就什么都理解了。這篇我們只講怎樣實現異步加載,對于滑動時停止加載的事下篇再講。
實現效果:
1、異步加載圖片,在加載圖片時,先加載一個默認的圖片,然后在后臺加載圖片,加載完成后顯示出來;
2、當用戶在滑動時,停止加載圖片的線程,當停止滑動時,看哪幾個ITEM在顯示屏內,只加載這幾個,其它線程保持阻止;(下篇再講)
效果圖:
? ? ? ? ? 剛開始加載時 ? ? ? ? ? ? ? ? ? ? ? ? ?向下劃動(新劃出來的是空白塊) ? ? ? ? ? 停劃,加載完成
????
一、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、列表子項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、主頁面代碼(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;??????????}??}??
上面兩個代碼一塊講
1、ImageAndText類是用來存儲要與XML綁定的圖片地址和名字地址的。
2、將所有的地址都放在一個List里面(dataArray),然后將其傳入ImageAndTextListAdapter()函數中;可見這個ImageAndTextListAdapter()函數是根據傳進去的dataArray生成對應的Adapter的
3、然后將ImageAndTextListAdapter()返回的Adapter與listView綁定
3、ImageAndTextListAdapter.java
這是重寫于baseAdapter的類,由于重寫于baseAdapter,所以有幾個必須重寫的函數,getCount()、getItem()、getItemId()、getView(),我們先把總體代碼寫出來,只講一個getView()函數,其實函數就不講了,先著重說下getView()函數在什么時候被系統調用:
getView()函數在什么時候被系統調用:
注意一點是Android系統在顯示列表時,并不是把所有代表都顯示出來,讓你隨便劃,劃到哪是哪;而是根據當前的在劃到的ITEM,調用當前ITEM的getView()來顯示它。
全部代碼:
[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()函數
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);??
這段代碼沒什么特別的就是將前面dataArray的信息與XML的元素項對應起來,并綁定,最關鍵的是下面這段,下面這個方法才是實現異步加載圖片的關鍵:
[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類的實例(asyncImageLoader),調用方法loadDrawable()方法,就實現了加載后圖像的綁定;好神奇,仔細看他是怎么做到的。這里先注意的有兩點:
(1)、傳進去的參數,當前項的位置(position),當前圖片的URL(imageUrl),一個名稱為ImageCallback()接口函數;
(2)、ImageCallback()接口函數里的兩個被重寫的函數onImageLoad()和onError()
3、AsyncImageLoader.java
從上面的講解也應該能猜到這個類,主要的功能就是加載圖片,然后成功后更新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)首先注意,剛才我們調用的loadDrawable()函數,里面初始化并運行了一個線程,而這個線程的里面只有一個函數LoadImg(),對于這個函數下面我們具體講,它的主要功能就是加載圖片,然后更新UI
(2)上面也看出了ImageCallback是一個接口,而里面的兩個函數onImageLoad()和onError()在這里是沒有具體實現的,那在哪里實現呢,當然是我們上面的ImageAndTextListAdapter.java里面了,等下我們具體會再講。
再往下看
[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()函數,就是根據URL到網上加載圖片,然后返回圖片流Drawable類型變量
(2)、對于LoadImg()我們再拆一下,先看如何在緩存中加載
[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、在這里就已經得到了圖像
[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;??}??
當我們得到圖像之后,調用imageCallback.onImageLoad(pos, drawable);來更新UI,由于我們再回來看看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中!!!!這就實現了回調
OK,就到這吧,OnError()的原理一樣,只不過是對程序沒有加載到圖片時應該怎么處理,其實就是當沒有加載到圖片時就是默認圖片代替。
下面給出源碼:http://download.csdn.net/detail/harvic880925/6802241(不要分,僅供分享)
請大家尊重作者板權,轉載請標明出處:
http://blog.csdn.net/harvic880925/article/details/17766027?
,謝謝!
總結
以上是生活随笔為你收集整理的异步加载图片(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。