慕课网:Android异步加载AsyncTask项目实战中

来源:互联网 发布:北上广不相信眼泪 知乎 编辑:程序博客网 时间:2024/06/06 07:19

上一篇,我们完成了使用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

@Overridepublic 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

@Overridepublic 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获取网络图片极其优化

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.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;}@Overrideprotected Bitmap doInBackground(String... params) {return getBitmapFromURL(params[0]);}@Overrideprotected 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
@Overridepublic 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;}
其运行效果和上面的一样。

全部代码下载地址:
http://download.csdn.net/detail/btt2013/9336381





0 0