本文实例讲述了Android实现ListView异步加载图片的方法。分享给大家供大家参考。具体如下:
ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,不用让用户等待下去,下面就说实现方法,先贴上主方法的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
package
cn.wangmeng.test;
import
java.io.IOException;
import
java.io.InputStream;
import
java.lang.ref.SoftReference;
import
java.net.MalformedURLException;
import
java.net.URL;
import
java.util.HashMap;
import
android.graphics.drawable.Drawable;
import
android.os.Handler;
import
android.os.Message;
public
class
AsyncImageLoader {
private
HashMap<String, SoftReference<Drawable>> imageCache;
public
AsyncImageLoader() {
imageCache =
new
HashMap<String, SoftReference<Drawable>>();
}
public
Drawable loadDrawable(
final
String imageUrl,
final
ImageCallback imageCallback) {
if
(imageCache.containsKey(imageUrl)) {
SoftReference<Drawable> softReference = imageCache.get(imageUrl);
Drawable drawable = softReference.get();
if
(drawable !=
null
) {
return
drawable;
}
}
final
Handler handler =
new
Handler() {
public
void
handleMessage(Message message) {
imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
}
};
new
Thread() {
@Override
public
void
run() {
Drawable drawable = loadImageFromUrl(imageUrl);
imageCache.put(imageUrl,
new
SoftReference<Drawable>(drawable));
Message message = handler.obtainMessage(
0
, drawable);
handler.sendMessage(message);
}
}.start();
return
null
;
}
public
static
Drawable loadImageFromUrl(String url) {
URL m;
InputStream i =
null
;
try
{
m =
new
URL(url);
i = (InputStream) m.getContent();
}
catch
(MalformedURLException e1) {
e1.printStackTrace();
}
catch
(IOException e) {
e.printStackTrace();
}
Drawable d = Drawable.createFromStream(i,
"src"
);
return
d;
}
public
interface
ImageCallback {
public
void
imageLoaded(Drawable imageDrawable, String imageUrl);
}
}
|
以上代码是实现异步获取图片的主方法,SoftReference是软引用,是为了更好的为了系统回收变量,重复的URL直接返回已有的资源,实现回调函数,让数据成功后,更新到UI线程。
几个辅助类文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package
cn.wangmeng.test;
import
android.view.View;
import
android.widget.ImageView;
import
android.widget.TextView;
public
class
ViewCache {
private
View baseView;
private
TextView textView;
private
ImageView imageView;
public
ViewCache(View baseView) {
this
.baseView = baseView;
}
public
TextView getTextView() {
if
(textView ==
null
) {
textView = (TextView) baseView.findViewById(R.id.text);
}
return
textView;
}
public
ImageView getImageView() {
if
(imageView ==
null
) {
imageView = (ImageView) baseView.findViewById(R.id.image);
}
return
imageView;
}
}
|
ViewCache是辅助获取adapter的子元素布局:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
package
cn.wangmeng.test;
import
java.util.List;
import
cn.wangmeng.test.AsyncImageLoader.ImageCallback;
import
android.app.Activity;
import
android.graphics.drawable.Drawable;
import
android.view.LayoutInflater;
import
android.view.View;
import
android.view.ViewGroup;
import
android.widget.ArrayAdapter;
import
android.widget.ImageView;
import
android.widget.ListView;
import
android.widget.TextView;
public
class
ImageAndTextListAdapter
extends
ArrayAdapter<ImageAndText> {
private
ListView listView;
private
AsyncImageLoader asyncImageLoader;
public
ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {
super
(activity,
0
, imageAndTexts);
this
.listView = listView;
asyncImageLoader =
new
AsyncImageLoader();
}
public
View getView(
int
position, View convertView, ViewGroup parent) {
Activity activity = (Activity) getContext();
// Inflate the views from XML
View rowView = convertView;
ViewCache viewCache;
if
(rowView ==
null
) {
LayoutInflater inflater = activity.getLayoutInflater();
rowView = inflater.inflate(R.layout.image_and_text_row,
null
);
viewCache =
new
ViewCache(rowView);
rowView.setTag(viewCache);
}
else
{
viewCache = (ViewCache) rowView.getTag();
}
ImageAndText imageAndText = getItem(position);
// Load the image and set it on the ImageView
String imageUrl = imageAndText.getImageUrl();
ImageView imageView = viewCache.getImageView();
imageView.setTag(imageUrl);
Drawable cachedImage = asyncImageLoader.loadDrawable(imageUrl,
new
ImageCallback() {
public
void
imageLoaded(Drawable imageDrawable, String imageUrl) {
ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
if
(imageViewByTag !=
null
) {
imageViewByTag.setImageDrawable(imageDrawable);
}
}
});
if
(cachedImage ==
null
) {
imageView.setImageResource(R.drawable.default_image);
}
else
{
imageView.setImageDrawable(cachedImage);
}
// Set the text on the TextView
TextView textView = viewCache.getTextView();
textView.setText(imageAndText.getText());
return
rowView;
}
}
|
ImageAndTextListAdapter是实现ListView的Adapter,里面有个技巧就是imageView.setTag(imageUrl),setTag是存储数据的,这样是为了保证在回调函数时,listview去更新自己对应item,大家仔细阅读就知道了。
最后贴出布局文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
android:orientation
=
"horizontal"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
>
<
ImageView
android:id
=
"@+id/image"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
/>
<
TextView
android:id
=
"@+id/text"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
/>
</
LinearLayout
>
|
运行效果截图如下:
