会导入库?会使用SimpleAdapter?那么恭喜你,看了本文你会发现ListView网络图片的异步延迟加载并缓存SDcard……so easy!
相信每一个刚刚接触ListView,需要实现网络图片加载功能的时候:从启动新线程异步下载网络图片开始,一直到最后实现图片的延迟加载并缓存SDcard,都会被各种各样的问题折磨到。记得当时自己是花了整整两天时间才完全实现了全部的功能要求,即使后来学习使用开源框架ImageLoader,也还是花了好一会儿才配置好能够使用!也是因为这一系列的问题,使笔者想着如何能把那些让大多开发者不需要走或者繁杂的步骤封装起来,以便更好使用,下面是方法:
1)首先,我们需要有开源框架ImageLoader,官方网址:https://github.com/dodola/Android-Universal-Image-Loader,点击页面右侧的download ZIP按钮,下载压缩包,然后解压,将其中的library库导入自己的项目中(不想官网下载的话library可直接使用我附件上传的)
2)然后下载附件,拷贝下载附件中的ImageSimpleAdapter.java 跟 AbsListViewBaseActivity.java到自己的项目中。拷贝完成后ImageSimpleAdapter.java会报错,找到报错行,发现是因为DisplayImageOptions options初始化时候资源找不到:(XXXX cannot be resolved or is not a field)
DisplayImageOptions options = new DisplayImageOptions.Builder() .showStubImage(R.drawable.ic_stub).showImageForEmptyUri(R.drawable.ic_empty).showImageOnFail(R.drawable.ic_error).cacheInMemory().cacheOnDisc() .displayer(new RoundedBitmapDisplayer(5)).build();
解压压缩包中的DisplayImageOptions图片.rar ,将里面的三张图片复制到res/drawable文件夹中,或者替换成自己想要的
三张图片对应关系如下:
R.drawable.ic_stub //加载开始默认的图片,滚动时候会显示
R.drawable.ic_empty //为空时候显示该图片
R.drawable.ic_error //加载图片出现问题时,会显示该图片
.displayer(
new
RoundedBitmapDisplayer(
5
)) //
RoundedBitmapDisplayer(
5
),参数作用是
设置图片圆角,0表示无圆角效果
注:使用开源框架ImageLoader因为涉及到internet访问跟图片缓存,所以需要得到使用权限:"android.permission.INTERNET"跟"android.permission.WRITE_EXTERNAL_STORAGE",养成习惯随时添加需要用到的权限。
3)到此,准备工作已经全部完成。接下来就是自己的代码了,自己代码很简单,将自己ListView所在的Activity继承AbsListViewBaseActivity,然后findViewById()找到自己的ListView设置ImageSimpleAdapter适配器。ListVIew配置ImageSimpleAdapter跟配置SimpleAdapter的的方法完全一样!只是因为涉及到网络下载,为了保证程序稳定,所以需要新启线程,参考代码如下:
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.os.Bundle; import android.widget.ListView; public class MainActivity extends AbsListViewBaseActivity { int[] mTo = new int[]{R.id.imageView1, R.id.textView1}; String[] mFrom = new String[]{"image", "text"}; List<HashMap<String, Object>> mAllData = new ArrayList<HashMap<String, Object>>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView1); new Thread() { public void run() { //因为我是测试,所以是用hfs搭建模拟的简单服务器。HttpDownload.urlDownload(String httpFilePath)是自己写的,作用通过一个传入的json文件的下载地址,返回得到json文件的内容字符串, String jsonStr = HttpDownload.urlDownload("http://10.0.2.2:8080/http_server/tongzhi.txt"); try { // JSONArray jsonArray = new JSONArray(jsonStr); for (int i = 0; i < jsonArray.length(); i ++) { JSONObject jsonObj = jsonArray.getJSONObject(i); //image 是解析出来的每一行图片的图片地址 String image = jsonObj.getString("image"); String replyer = jsonObj.getString("replyer"); HashMap<String, Object> map = new HashMap<String, Object>(); map.put("image", image); map.put("replyer", replyer); //根据解析到的数据,构造List<HashMap<String, Object>> mAllData 的数据 mAllData.add(map); } runOnUiThread(new Runnable() { public void run() { //R.layout .item_list 是ListView 的行布局,很简单,一个ImageView、一个TextView,很简单,所以布局文件就不贴了 ((ListView)listView).setAdapter(new ImageSimpleAdapter(MainActivity.this, mTo, mFrom, mAllData, R.layout .item_list)); } }); } catch (JSONException e) { e.printStackTrace(); } }; }.start(); } }
上面代码33行有用到我自己写的一个小模块,作用是通过一个传入的json文件的下载地址,返回得到json文件的内容字符串以便解析,源代码如下:
import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import org.apache.http.util.ByteArrayBuffer; public class HttpDownload { private HttpDownload(){}; public static String urlDownload(String httpFilePath) { String result; InputStream is = null; try { ByteArrayBuffer arrayBuffer = new ByteArrayBuffer(2000); URL url = new URL(httpFilePath); URLConnection connection = url.openConnection(); is = connection.getInputStream(); int length = 0; byte[] buffer = new byte[1024]; while(-1 != (length = is.read(buffer))) { arrayBuffer.append(buffer, 0, length); } result = new String(arrayBuffer.toByteArray(), 0, arrayBuffer.length()).toString(); return result; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } }
4)至此,全部步骤完成。我个人修改、封装了的关键代码都在附件中的ImageSimpleAdapter里,有兴趣的可以自己看看实现方法,都有详细注释,有不清楚的或者有更好意见的,可以留言探讨或者联系我(*^__^*) ~。邮箱:[email protected]
(其实ImageSimpleAdapter等我自己写的有些部分都可以放到附件里上传的那个library里,这样前两步骤很多就都可以省掉了。不过这样的话,如果想自定义延迟加载状态等的显示图片还有圆角大小时候就不方便了。看自己选择,有兴趣的可以试试)