上一篇,我们完成了使用AsyncTask异步加载获取了网络的数据,并且解析数据,顺利显示在了ListView中,但是其中图片还是使用的是本地的默认图片,并没有从网络获取图片,今天我们完成从网络获取图片的两种方法:
1.使用线程获取网络图片极其优化
ImageLoader.java
package com.xbmu.news;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
public class ImageLoader {
private ImageView mImageView;
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
super.handleMessage(msg);
mImageView.setImageBitmap((Bitmap)msg.obj);
};
};
/**
* 通过线程去显示图片
* @param imageView
* @param url
*/
public void showImageByThread(ImageView imageView, final String url) {
mImageView = imageView;//将imageView的对象传递给引用。没有这条语句,会发生空指针异常
new Thread() {
public void run() {
super.run();
Bitmap bitmap = getBitmapFromURL(url);
Message message = Message.obtain();
message.obj = bitmap;
mHandler.sendMessage(message);
};
}.start();
}
public Bitmap getBitmapFromURL(String urlString) {
Bitmap bitmap;
InputStream is = null;
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
is = new BufferedInputStream(connection.getInputStream());
bitmap = BitmapFactory.decodeStream(is);
connection.disconnect();//断开连接
return bitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try{
is.close();//关闭流
}catch(IOException e){
e.printStackTrace();
}
}
return null;
}
}
修改适配器:NewsAdapter.java
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if(convertView == null){
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item_layout, null);
viewHolder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon);
viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);
viewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.ivIcon.setImageResource(R.drawable.ic_launcher);//先设置图片为默认本地图片
//从网络加载图片
new ImageLoader().showImageByThread(viewHolder.ivIcon,mList.get(position).newsImgae);
viewHolder.tvTitle.setText(mList.get(position).newsTitle);
viewHolder.tvContent.setText(mList.get(position).newsContent);
return convertView;
}
运行效果
仔细观察运行效果,并分析问题所在
出现的问题:看上去完美无缺,所有的图片都显示出来了,但是会发现这里的图片刷新显示的时候,会刷新多次,很多图片并不是一次加载成功。
分析原因:是因为ListView的缓存机制,ListView具有重用convertView的功能,这一条convertView,它可能是前面或后面这样一个缓冲池中的某一个View,当我们切换ListView的选项的时候,它会从缓冲池中取出已经存在的convertView,而这个convertView的图像是已经显示出来的。就会导致新的图片在加载前会先显示一下旧的图片。
解决方法:图片显示错位的原因在于正确的ListView没有显示正确的url。viewHolder.ivIcon.setTag(url)设置tag作为身份表标志,将url设置为身份验证码,
我们给这样的一个imageView设置了一个名为url的tag,也就是将这样的一个imageview和对应的URL中的图片进行了绑定。我们在获取图片的时候,需要进行判断,这样避免了缓存的图片对正确的图片的一个影响。
代码实现:
修改NewsAdapter.java
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if(convertView == null){
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item_layout, null);
viewHolder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon);
viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);
viewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.ivIcon.setImageResource(R.drawable.ic_launcher);//先设置图片为默认本地图片
String url = mList.get(position).newsImgae;
viewHolder.ivIcon.setTag(url);//给ImageView设置tag标志,将url设置为身份验证码
//从网络加载图片
new ImageLoader().showImageByThread(viewHolder.ivIcon,url);
viewHolder.tvTitle.setText(mList.get(position).newsTitle);
viewHolder.tvContent.setText(mList.get(position).newsContent);
return convertView;
}
修改ImageLoader.java
public class ImageLoader {
private ImageView mImageView;
private String mUrl;
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(mImageView.getTag().equals(mUrl)){
mImageView.setImageBitmap((Bitmap)msg.obj);
}
};
};
/**
* 通过线程去显示图片
* @param imageView
* @param url
*/
public void showImageByThread(ImageView imageView, final String url) {
mImageView = imageView;//将imageView的对象传递给引用。没有这条语句,会发生空指针异常
mUrl = url;
new Thread() {
public void run() {
super.run();
Bitmap bitmap = getBitmapFromURL(url);
Message message = Message.obtain();
message.obj = bitmap;
mHandler.sendMessage(message);
};
}.start();
}
.......
}
运行效果图:
2.使用AsyncTask获取网络图片极其优化
package com.xbmu.news;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;
public class ImageLoader {
/**
* 通过AsyncTask异步加载从网络获取图片
* @param imageView
* @param url
*/
public void showImageByAsyncTask(ImageView imageView,String url){
new NewsAsyncTask(imageView,url).execute(url);
}
private class NewsAsyncTask extends AsyncTask<String, Void, Bitmap>{
private ImageView mImageView;
private String mUrl;
public NewsAsyncTask(ImageView imageView,String url) {
mImageView = imageView;
mUrl = url;
}
@Override
protected Bitmap doInBackground(String... params) {
return getBitmapFromURL(params[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if(mImageView.getTag().equals(mUrl)){
mImageView.setImageBitmap(bitmap);
}
}
}
public Bitmap getBitmapFromURL(String urlString) {
Bitmap bitmap;
InputStream is = null;
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
is = new BufferedInputStream(connection.getInputStream());
bitmap = BitmapFactory.decodeStream(is);
connection.disconnect();//断开连接
return bitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try{
is.close();//关闭流
}catch(IOException e){
e.printStackTrace();
}
}
return null;
}
}
修改
NewsAdapter.java
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if(convertView == null){
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item_layout, null);
viewHolder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon);
viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);
viewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.ivIcon.setImageResource(R.drawable.ic_launcher);//先设置图片为默认本地图片
String url = mList.get(position).newsImgae;
viewHolder.ivIcon.setTag(url);//给ImageView设置tag标志,将url设置为身份验证码
//从网络加载图片
new ImageLoader().showImageByAsyncTask(viewHolder.ivIcon, url);
viewHolder.tvTitle.setText(mList.get(position).newsTitle);
viewHolder.tvContent.setText(mList.get(position).newsContent);
return convertView;
}