一般,我们使用listview加载图片时,有很多的jar包已经封装的很好,我们只需要知道怎么使用就可以,比如常用的imageLoader,使用非常的方便。但是,我们也要知道自己怎么用listview异步加载图片。昨天,在网上找了资料,自己总算是做出来了。
1.新建一个普通的listview,每个item里存放一个imageview和textView,然后做好一个适配器adapter。
adapter的getview()和普通的listview一样,编写很简单。
public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView = null; TextView textView = null; if (convertView == null) { convertView = layoutInflater.inflate(listviewItem, null); // 获取条目的view对象 imageView = (ImageView) convertView.findViewById(R.id.imageView); textView = (TextView) convertView.findViewById(R.id.textView); convertView.setTag(new DataWrapper(imageView, textView)); } else { DataWrapper dataWrapper = (DataWrapper) convertView.getTag(); imageView = dataWrapper.imageView; textView = dataWrapper.textView; imageView.setTag(position); } Contact contact = data.get(position); textView.setText(contact.name); //=====初始化时加载图片 if (isInit==false){ asyncImageLoad(imageView, contact.image); } retu
在getView里,asyncImageLoad(imageView, contact.image);是用来异步加载图片的,每次调用getView()时,通过传递imageview和图片的网络地址,开启一个异步任务,去网络下载图片,下载后,首先存入缓存,然后存入sd卡,下载完成后显示在listview上,下载调用时会先从软引用寻找图片,用的话直接显示图片,如果没有,则从sd卡找图片,有的话显示图片,如果没有,则进行网络请求。
2.编写异步请求的代码。
private void asyncImageLoad(ImageView imageView, String path) { if (imageCache.containsKey(path)) { SoftReference<Drawable> softReference = imageCache.get(path); Drawable drawable = softReference.get(); if (drawable != null) { imageView.setImageDrawable(drawable); Log.e("Test_path",""+path); return; } } Log.e("Test_path2",""+path); AsyncImageTask asyncImageTask = new AsyncImageTask(imageView); asyncImageTask.execute(path); }
这其中用到一个异步加载的类AsyncImageTask,当每次请求网络图片时,获得图片后,会把图片存入软引用。
private final class AsyncImageTask extends AsyncTask<String, Integer, Uri> { private ImageView imageView; private String imageUrl; public AsyncImageTask(ImageView imageView) { this.imageView = imageView; } protected Uri doInBackground(String... params) {// 子线程中执行的 try { imageUrl=params[0]; return ContactService.getImage(params[0], cache); } catch (Exception e) { e.printStackTrace(); } return null; } protected void onPostExecute(Uri result) {// 运行在主线程 if (result != null && imageView != null) imageView.setImageURI(result); Drawable drawable =imageView.getDrawable(); imageCache.put(imageUrl, new SoftReference<Drawable>(drawable)); } }
在doInBackground()内开启了线程,进行网络请求。
public static Uri getImage(String path, File cacheDir) throws Exception{// path -> MD5 ->32字符串.jpg File localFile = new File(cacheDir, MD5.getMD5(path)+ path.substring(path.lastIndexOf("."))); if(localFile.exists()){ return Uri.fromFile(localFile); }else{ Log.e("Test_MD5",""+path); HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); if(conn.getResponseCode() == 200){ FileOutputStream outStream = new FileOutputStream(localFile); InputStream inputStream = conn.getInputStream(); byte[] buffer = new byte[1024]; int len = 0; while( (len = inputStream.read(buffer)) != -1){ outStream.write(buffer, 0, len); } inputStream.close(); outStream.close(); return Uri.fromFile(localFile); } } return null; }
getImage()内用get()去请求图片,然后获得图片后,存入sd卡,然后返回图片存入文件的URI。
然后,AsyncImageTask的onPostExecute()获得URI,然后通过imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));设置图片。
这样就完成了图片的异步加载。这时滑动listview,会发现滑动有卡顿,所以可以设置listview的滑动监听。
mListView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView absListView, int scrollState) { switch (scrollState) { case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:// 滑动停止 isInit=true; for (; start_index < end_index; start_index++) { ImageView imageView = (ImageView) mListView.findViewWithTag(start_index); Contact contact = ContactAdapter.this.data.get(start_index); if (imageView!=null){ asyncImageLoad(imageView, contact.image); }else { Log.e("Test2",""+imageView); } } break; default: break; } } @Override public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) { start_index = firstVisibleItem; end_index = firstVisibleItem + visibleItemCount; } });
其中ImageView imageView = (ImageView) mListView.findViewWithTag(start_index);是因为在getview()内我设置了imageview的Tag.imageView.setTag(position);然后在空闲的状态下调用异步加载图片。
这样就完成了异步加载,与滑动不加载的功能。