您的位置:首页 > 移动开发 > Android开发

Android实现ListView异步加载图片

2010-06-22 13:25 597 查看

Android实现ListView异步加载图片

ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,不用让用户等待下去,下面就说实现方法,先贴上主方法的代码: 

01.
package
 
cn.wangmeng.test;

02.
 
03.
import
 
java.io.IOException;

04.
import
 
java.io.InputStream;

05.
import
 
java.lang.ref.SoftReference;

06.
import
 
java.net.MalformedURLException;

07.
import
 
java.net.URL;

08.
import
 
java.util.HashMap;

09.
 
10.
import
 
android.graphics.drawable.Drawable;

11.
import
 
android.os.Handler;

12.
import
 
android.os.Message;

13.
 
14.
public
 
class
 
AsyncImageLoader {

15.
 
16.
     
private
 
HashMap<String, SoftReference<Drawable>> imageCache;

17.
      
 
18.
         
public
 
AsyncImageLoader() {

19.
             
imageCache = 
new
 
HashMap<String, SoftReference<Drawable>>();

20.
         
}

21.
      
 
22.
         
public
 
Drawable loadDrawable(
final
 
String imageUrl, 
final
 
ImageCallback imageCallback) {

23.
             
if
 
(imageCache.containsKey(imageUrl)) {

24.
                 
SoftReference<Drawable> softReference = imageCache.get(imageUrl);

25.
                 
Drawable drawable = softReference.get();

26.
                 
if
 
(drawable != 
null
) {

27.
                     
return
 
drawable;

28.
                 
}

29.
             
}

30.
             
final
 
Handler handler = 
new
 
Handler() {

31.
                 
public
 
void
 
handleMessage(Message message) {

32.
                     
imageCallback.imageLoaded((Drawable) message.obj, imageUrl);

33.
                 
}

34.
             
};

35.
             
new
 
Thread() {

36.
                 
@Override

37.
                 
public
 
void
 
run() {

38.
                     
Drawable drawable = loadImageFromUrl(imageUrl);

39.
                     
imageCache.put(imageUrl, 
new
 
SoftReference<Drawable>(drawable));

40.
                     
Message message = handler.obtainMessage(
0
, drawable);

41.
                     
handler.sendMessage(message);

42.
                 
}

43.
             
}.start();

44.
             
return
 
null
;

45.
         
}

46.
      
 
47.
        
public
 
static
 
Drawable loadImageFromUrl(String url) {

48.
            
URL m;

49.
            
InputStream i = 
null
;

50.
            
try
 
{

51.
                
m = 
new
 
URL(url);

52.
                
i = (InputStream) m.getContent();

53.
            
catch
 
(MalformedURLException e1) {

54.
                
e1.printStackTrace();

55.
            
catch
 
(IOException e) {

56.
                
e.printStackTrace();

57.
            
}

58.
            
Drawable d = Drawable.createFromStream(i, 
"src"
);

59.
            
return
 
d;

60.
        
}

61.
      
 
62.
         
public
 
interface
 
ImageCallback {

63.
             
public
 
void
 
imageLoaded(Drawable imageDrawable, String imageUrl);

64.
         
}

65.
 
66.
}


以上代码是实现异步获取图片的主方法,SoftReference是软引用,是为了更好的为了系统回收变量,重复的URL直接返回已有的资源,实现回调函数,让数据成功后,更新到UI线程。 
几个辅助类文件:

view source

print?

01.
package
 
cn.wangmeng.test;

02.
 
03.
public
 
class
 
ImageAndText {

04.
        
private
 
String imageUrl;

05.
        
private
 
String text;

06.
 
07.
        
public
 
ImageAndText(String imageUrl, String text) {

08.
            
this
.imageUrl = imageUrl;

09.
            
this
.text = text;

10.
        
}

11.
        
public
 
String getImageUrl() {

12.
            
return
 
imageUrl;

13.
        
}

14.
        
public
 
String getText() {

15.
            
return
 
text;

16.
        
}

17.
}


view source

print?

01.
package
 
cn.wangmeng.test;

02.
 
03.
import
 
android.view.View;

04.
import
 
android.widget.ImageView;

05.
import
 
android.widget.TextView;

06.
 
07.
public
 
class
 
ViewCache {

08.
 
09.
        
private
 
View baseView;

10.
        
private
 
TextView textView;

11.
        
private
 
ImageView imageView;

12.
 
13.
        
public
 
ViewCache(View baseView) {

14.
            
this
.baseView = baseView;

15.
        
}

16.
 
17.
        
public
 
TextView getTextView() {

18.
            
if
 
(textView == 
null
) {

19.
                
textView = (TextView) baseView.findViewById(R.id.text);

20.
            
}

21.
            
return
 
textView;

22.
        
}

23.
 
24.
        
public
 
ImageView getImageView() {

25.
            
if
 
(imageView == 
null
) {

26.
                
imageView = (ImageView) baseView.findViewById(R.id.image);

27.
            
}

28.
            
return
 
imageView;

29.
        
}

30.
 
31.
}


ViewCache是辅助获取adapter的子元素布局 

view source

print?

01.
package
 
cn.wangmeng.test;

02.
 
03.
import
 
java.util.List;

04.
 
05.
import
 
cn.wangmeng.test.AsyncImageLoader.ImageCallback;

06.
 
07.
import
 
android.app.Activity;

08.
import
 
android.graphics.drawable.Drawable;

09.
import
 
android.view.LayoutInflater;

10.
import
 
android.view.View;

11.
import
 
android.view.ViewGroup;

12.
import
 
android.widget.ArrayAdapter;

13.
import
 
android.widget.ImageView;

14.
import
 
android.widget.ListView;

15.
import
 
android.widget.TextView;

16.
 
17.
public
 
class
 
ImageAndTextListAdapter 
extends
 
ArrayAdapter<ImageAndText> {

18.
 
19.
        
private
 
ListView listView;

20.
        
private
 
AsyncImageLoader asyncImageLoader;

21.
 
22.
        
public
 
ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {

23.
            
super
(activity, 
0
, imageAndTexts);

24.
            
this
.listView = listView;

25.
            
asyncImageLoader = 
new
 
AsyncImageLoader();

26.
        
}

27.
 
28.
        
public
 
View getView(
int
 
position, View convertView, ViewGroup parent) {

29.
            
Activity activity = (Activity) getContext();

30.
 
31.
            
// Inflate the views from XML

32.
            
View rowView = convertView;

33.
            
ViewCache viewCache;

34.
            
if
 
(rowView == 
null
) {

35.
                
LayoutInflater inflater = activity.getLayoutInflater();

36.
                
rowView = inflater.inflate(R.layout.image_and_text_row, 
null
);

37.
                
viewCache = 
new
 
ViewCache(rowView);

38.
                
rowView.setTag(viewCache);

39.
            
else
 
{

40.
                
viewCache = (ViewCache) rowView.getTag();

41.
            
}

42.
            
ImageAndText imageAndText = getItem(position);

43.
 
44.
            
// Load the image and set it on the ImageView

45.
            
String imageUrl = imageAndText.getImageUrl();

46.
            
ImageView imageView = viewCache.getImageView();

47.
            
imageView.setTag(imageUrl);

48.
            
Drawable cachedImage = asyncImageLoader.loadDrawable(imageUrl, 
new
 
ImageCallback() {

49.
                
public
 
void
 
imageLoaded(Drawable imageDrawable, String imageUrl) {

50.
                    
ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);

51.
                    
if
 
(imageViewByTag != 
null
) {

52.
                        
imageViewByTag.setImageDrawable(imageDrawable);

53.
                    
}

54.
                
}

55.
            
});

56.
            
if
 
(cachedImage == 
null
) {

57.
                
imageView.setImageResource(R.drawable.default_image);

58.
            
}
else
{

59.
                
imageView.setImageDrawable(cachedImage);

60.
            
}

61.
            
// Set the text on the TextView

62.
            
TextView textView = viewCache.getTextView();

63.
            
textView.setText(imageAndText.getText());

64.
 
65.
            
return
 
rowView;

66.
        
}

67.
 
68.
}


ImageAndTextListAdapter是实现ListView的Adapter,里面有个技巧就是imageView.setTag(imageUrl),setTag是存储数据的,这样是为了保证在回调函数时,listview去更新自己对应item,大家仔细阅读就知道了。 
最后贴出布局文件:

view source

print?

01.
<?
xml
 
version
=
"1.0"
 
encoding
=
"utf-8"
?>

02.
<
LinearLayout
 
xmlns:android
=
"http://schemas.android.com/apk/res/android"

03.
              
android:orientation
=
"horizontal"

04.
              
android:layout_width
=
"fill_parent"

05.
              
android:layout_height
=
"wrap_content"
>

06.
 
07.
        
<
ImageView
 
android:id
=
"@+id/image"

08.
                   
android:layout_width
=
"wrap_content"

09.
                   
android:layout_height
=
"wrap_content"

10.
                   
/>

11.
 
12.
        
<
TextView
 
android:id
=
"@+id/text"

13.
                  
android:layout_width
=
"wrap_content"

14.
                  
android:layout_height
=
"wrap_content"
/>

15.
 
16.
</
LinearLayout
>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息