上一篇,我们完成了使用AsyncTask异步加载获取了网络的数据,并且解析数据,顺利显示在了ListView中,但是其中图片还是使用的是本地的默认图片,并没有从网络获取图片,今天我们完成从网络获取图片的两种方法:
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(); } ....... }运行效果图:
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; }