Android加载网络图片
Android加载网络图片资源方式和加载字符串资源类式,也是通过Http连接解析返回的字节流InputStream实现
//构造URL类 URL url = new URL(httpUrl); //从url中得到图片输入流 InputStream in = url.openStream(); //使用BitmapFactory类解析流得到Bitmap对象 Bitmap bitmap = BitmapFactory.decodeStream(in);
注:InputStream in = url.openStream()
等价于
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
InputStream is = conn.getInputStream();
openStream()方法其实是对上面两行代码的封装
/** * Equivalent to {@code openConnection().getInputStream(types)}. */ public final InputStream openStream() throws IOException { return openConnection().getInputStream(); }
接着我们来实现一个网络加载单张图片实例
首先定义一个方法根据图片地址获取图片
public Bitmap downLoadBitmap(String httpUrl) { InputStream in = null; try { URL url = new URL(httpUrl); in = url.openStream(); Bitmap bitmap = BitmapFactory.decodeStream(in); return bitmap; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; }
加载网络图片是耗时操作我们需要在异步任务中调用
String httpUrl = "http://d.hiphotos.baidu.com/image/h%3D360/sign= ba3bf5f839c79f3d90e1e2368aa1cdbc/f636afc379310a55c01f6ef3b54543a9822610f9.jpg"; new AsyncTask<String, Void, Bitmap>() { protected void onPreExecute() { mProgressBar.setVisibility(View.VISIBLE); } @Override protected Bitmap doInBackground(String... params) { String httpUrl = params[0]; Bitmap bitmap = downLoadBitmap(httpUrl); return bitmap; } @Override protected void onPostExecute(Bitmap result) { mProgressBar.setVisibility(View.GONE); if (result != null) mShowImg.setImageBitmap(result); } }.execute(httpUrl);
界面部份使用imageView控件,ProgressBar显示加载中效果如下
接着我们在来看下实现多图加载操作
获取图片资源方式和单张图片一样,显示控件我们换用GridView.
主要代码如下
@Override public View getView(int position, View convertView, ViewGroup parent) { final ImageView loaderImageView; if (convertView == null) { convertView = mInflater.inflate(R.layout.item_my_gridview_layout, null); loaderImageView = (ImageView) convertView.findViewById(R.id.my_gridview_img); convertView.setTag(loaderImageView); } else { loaderImageView = (ImageView) convertView.getTag(); } String itemUrl = (String) getItem(position); new AsyncTask<String, Void, Bitmap>() { @Override protected Bitmap doInBackground(String... params) { String httpUrl = params[0]; //根据httpUrl地址加载网络图片 Bitmap bitmap = downLoadBitmap(httpUrl); return bitmap; } @Override protected void onPostExecute(Bitmap result) { if (result != null) loaderImageView.setImageBitmap(result); } }.execute(itemUrl); return convertView; } }
将AsyncTask放到适配器getView方法获取图片一屏的时候感觉不到问题,当我们图片很多时,上下滚动,这时会发现图片错位现象.
这是因为上下滚动时会不但重复调用getView方法启动AsyncTask.为了解决这个问题我们可以将AsyncTask进行保存,根据Url来控制是否启动AsyncTask,具体代码如下:
public void loadBitmap(Resources res,String imageUrl, ImageView imageView, int resId) { if (cancelPotentialWork(imageUrl, imageView)) { BitmapWorkerTask task = new BitmapWorkerTask(imageView); AsyncDrawable asyncDrawable = new AsyncDrawable(res, BitmapFactory.decodeResource(res, resId), task); imageView.setImageDrawable(asyncDrawable); task.execute(imageUrl); } } public static boolean cancelPotentialWork(String imageUrl, ImageView imageView) { final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (bitmapWorkerTask != null) { final String bitmapData = bitmapWorkerTask.imageUrl; if (!bitmapData.equals(imageUrl)) { // Cancel previous task bitmapWorkerTask.cancel(true); } else { // The same work is already in progress return false; } } // No task associated with the ImageView, or an existing task was // cancelled return true; } private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { if (imageView != null) { final Drawable drawable = imageView.getDrawable(); if (drawable instanceof AsyncDrawable) { final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; return asyncDrawable.getBitmapWorkerTask(); } } return null; } /** * 创建一个专用的Drawable的子类来储存返回工作任务的引用。在这种情况下,当任务完成时BitmapDrawable会被使用 * */ static class AsyncDrawable extends BitmapDrawable { private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference; public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { super(res, bitmap); bitmapWorkerTaskReference = new WeakReference<BitmapWorkerTask>( bitmapWorkerTask); } public BitmapWorkerTask getBitmapWorkerTask() { return (BitmapWorkerTask) bitmapWorkerTaskReference.get(); } } class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> { private final WeakReference<ImageView> imageViewReference; private String imageUrl = ""; public BitmapWorkerTask(ImageView imageView) { // Use a WeakReference to ensure the ImageView can be garbage // collected imageViewReference = new WeakReference<ImageView>(imageView); } // Decode image in background. @Override protected Bitmap doInBackground(String... params) { imageUrl = params[0]; return downLoadBitmap(imageUrl); } // Once complete, see if ImageView is still around and set bitmap. @Override protected void onPostExecute(Bitmap bitmap) { if (isCancelled()) { bitmap = null; } if (imageViewReference != null && bitmap != null) { final ImageView imageView = (ImageView) imageViewReference .get(); final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (this == bitmapWorkerTask && imageView != null) { imageView.setImageBitmap(bitmap); } } } }
转载请注明来源:Android加载网络图片