• 简单的ListView中item图片异步加载


    前言:

        在android开发当中,从目标地址获取图片往往都是采用异步加载的方法。当完全加载完图片后在进行显示,也有些是直接将加载的图片一点一点的显示出来。
    这两个区别只是对流的处理不同而已。现在就讲讲当图片被完全获取到后在显示的方法。
    一,效果图:
     
        初始化:                                                   获取后:
                           
        1.1,效果思路:
               初始化的时候默认ImageView显示一张白色的图片,在加载完图片以后,用心的图片将白色图片给替换掉,就达到效果了。
    二,代码实现:
        主要类介绍:
        AsyncImageLoadAdapter :ListView的自定义Adapter
        AsyncLoad :图片异步加载类
        MainActivity :主Activity。
    相关的布局文件就不介绍了,在后面看就行了。
    MainActivity:
     1 public class MainActivity extends Activity {
     2 
     3     private ListView listView;
     4 
     5     @Override
     6     protected void onCreate(Bundle savedInstanceState) {
     7         super.onCreate(savedInstanceState);
     8         setContentView(R.layout.activity_main);
     9         initView();
    10         initData();
    11     }
    12 
    13     private void initView() {
    14         listView = (ListView) findView(R.id.listView);
    15     }
    16 
    17     private void initData() {
    18         List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
    19         HashMap<String, Object> map1 = new HashMap<String, Object>();
    20         map1.put("img",
    21                 "http://img5.imgtn.bdimg.com/it/u=747474479,3247936386&fm=21&gp=0.jpg");
    22         map1.put("txt", "条目一");
    23         HashMap<String, Object> map2 = new HashMap<String, Object>();
    24         map2.put("img",
    25                 "http://pic.nipic.com/2007-12-22/2007122215556437_2.jpg");
    26         map2.put("txt", "条目二");
    27         HashMap<String, Object> map3 = new HashMap<String, Object>();
    28         map3.put("img",
    29                 "http://img1.imgtn.bdimg.com/it/u=1774561363,2410491846&fm=21&gp=0.jpg");
    30         map3.put("txt", "条目三");
    31         HashMap<String, Object> map4 = new HashMap<String, Object>();
    32         map4.put("img",
    33                 "http://img5.imgtn.bdimg.com/it/u=112049007,3368205326&fm=21&gp=0.jpg");
    34         map4.put("txt", "条目四");
    35         HashMap<String, Object> map5 = new HashMap<String, Object>();
    36         map5.put("img",
    37                 "http://img3.imgtn.bdimg.com/it/u=2953608063,4260501712&fm=21&gp=0.jpg");
    38         map5.put("txt", "条目五");
    39         list.add(map1);
    40         list.add(map2);
    41         list.add(map3);
    42         list.add(map4);
    43         list.add(map5);
    44         AsyncImageLoadAdapter adapter = new AsyncImageLoadAdapter(
    45                 MainActivity.this, list, listView);
    46         listView.setAdapter(adapter);
    47     }
    48 
    49     private <T> T findView(int id) {
    50         return (T) findViewById(id);
    51     }
    52 
    53 }
    这个MainActivity挺简单的,就是初始化相关控件,然后给ListView附上值而已。
     
     
    AsyncImageLoadAdapter :
      
     1 public class AsyncImageLoadAdapter extends BaseAdapter {
     2 
     3     private Context context;
     4 
     5     private List<HashMap<String, Object>> listData;
     6 
     7     private AsyncLoad asyncLoad;
     8 
     9     private ListView listView;
    10 
    11     public AsyncImageLoadAdapter(Context context1,
    12             List<HashMap<String, Object>> listData1, ListView listView1) {
    13         this.context = context1;
    14         this.listData = listData1;
    15         this.asyncLoad = AsyncLoad.instance();
    16         this.listView = listView1;
    17     }
    18 
    19     @Override
    20     public int getCount() {
    21         return listData.size();
    22     }
    23 
    24     @Override
    25     public Object getItem(int position) {
    26         return listData.get(position);
    27     }
    28 
    29     @Override
    30     public long getItemId(int position) {
    31         return position;
    32     }
    33 
    34     @Override
    35     public View getView(int position, View convertView, ViewGroup parent) {
    36 
    37         if (convertView == null) {
    38             convertView = LayoutInflater.from(context).inflate(
    39                     R.layout.list_item, null);
    40         }
    41 
    42         convertView.setTag(position);
    43         ImageView imageView = (ImageView) convertView
    44                 .findViewById(R.id.list_item_img);
    45         imageView.setBackgroundResource(R.drawable.img_black);
    46         TextView textView = (TextView) convertView
    47                 .findViewById(R.id.list_item_tv);
    48         textView.setText("我是条目" + position);
    49         HashMap<String, Object> item = listData.get(position);
    50         String imageStr = (String) item.get("img");
    51         asyncLoad.loadImage(position, imageStr, new ILoadListener() {
    52 
    53             @SuppressLint("NewApi")
    54             @Override
    55             public void onSuccess(Integer pos, Drawable drawable) {
    56                 View view = listView.findViewWithTag(pos);
    57 
    58                 if (view != null) {
    59                     ImageView img = (ImageView) view
    60                             .findViewById(R.id.list_item_img);
    61 
    62                     img.setBackground(drawable);
    63                 }
    64             }
    65 
    66             @Override
    67             public void onFail(String failStr) {
    68                 Toast.makeText(context, "错误信息是->" + failStr, Toast.LENGTH_SHORT)
    69                         .show();
    70             }
    71         });
    72 
    73         return convertView;
    74     }
    75 }

    这个Adapter中加载了一个list_item布局(adapter中未用ViewHolder,不要去纠结这个,加上也可),来初始化未加载图片的时候。主要要说的是这段代码

     1 asyncLoad.loadImage(position, imageStr, new ILoadListener() {
     2    @SuppressLint("NewApi")
     3    @Override
     4    public void onSuccess(Integer pos, Drawable drawable) {
     5     View view = listView.findViewWithTag(pos);
     6     if (view != null) {
     7      ImageView img = (ImageView) view
     8        .findViewById(R.id.list_item_img);
     9      img.setBackground(drawable);
    10     }
    11    }
    12    @Override
    13    public void onFail(String failStr) {
    14     Toast.makeText(context, "错误信息是->" + failStr, Toast.LENGTH_SHORT)
    15       .show();
    16    }
    17   });
    这段代码就进行了异步去加载图片。
    思路是:先将ListView中的每个item设置一个Tag,便于后面找到对应的item中imageView进行图片更新。
    然后利用图片加载类去网络获取图片,获取到图片后采用接口回调的方式传回图片进行ImageView更新(UI线程中
    执行的)
     
     
      AsyncLoad:
      
      1 public class AsyncLoad {
      2 
      3     private static AsyncLoad asyncLoad;
      4     /**
      5      * 图片缓存容器,采用软引用,当用户手机内存不够时候,系统自动回收其所占有的内存
      6      */
      7     private HashMap<String, SoftReference<Drawable>> dataMap;
      8     /**
      9      * 用于在UI线程中进行UI更新
     10      */
     11     private Handler handler = new Handler();
     12 
     13     public synchronized static AsyncLoad instance() {
     14 
     15         if (asyncLoad == null)
     16             asyncLoad = new AsyncLoad();
     17         return asyncLoad;
     18 
     19     }
     20 
     21     public AsyncLoad() {
     22         dataMap = new HashMap<String, SoftReference<Drawable>>();
     23     }
     24 
     25     // 内部接口对图片获取的监听
     26     interface ILoadListener {
     27         /**
     28          * 图片加载成功后
     29          * 
     30          * @param pos
     31          *            对listView中pos位置
     32          * @param drawable
     33          *            网络加载后获取到的图片
     34          */
     35         public void onSuccess(Integer pos, Drawable drawable);
     36 
     37         public void onFail(String failStr);
     38 
     39     }
     40 
     41     /**
     42      * 开启线程对图片进行加载
     43      * 
     44      * @param pos
     45      *            listView的pos位置进行加载
     46      * @param imageStr
     47      *            图片地址
     48      * @param listener
     49      *            监听接口
     50      */
     51 
     52     public void loadImage(final Integer pos, final String imageStr,
     53             final ILoadListener listener) {
     54 
     55         // 开启一个线程获取图片资源
     56         new Thread(new Runnable() {
     57 
     58             @Override
     59             public void run() {
     60                 try {
     61                     Thread.sleep(5000);
     62                 } catch (InterruptedException e) {
     63                     e.printStackTrace();
     64                 }
     65                 load(pos, imageStr, listener);
     66             }
     67         }).start();
     68 
     69     }
     70 
     71     private void load(final Integer pos, final String imageStr,
     72             final ILoadListener listener) {
     73 
     74         if (dataMap.containsKey(imageStr)) {
     75 
     76             SoftReference<Drawable> softReference = dataMap.get(imageStr);
     77             final Drawable d = softReference.get();
     78             if (d != null) {
     79                 handler.post(new Runnable() {
     80 
     81                     @Override
     82                     public void run() {
     83 
     84                         listener.onSuccess(pos, d);
     85                     }
     86                 });
     87             }
     88             return;
     89 
     90         }
     91 
     92         try {
     93             final Drawable d = loadImgFromUrl(imageStr);
     94             if (d != null) {
     95                 SoftReference<Drawable> soft = new SoftReference<Drawable>(d);
     96                 dataMap.put(imageStr, soft);
     97             }
     98             handler.post(new Runnable() {
     99 
    100                 @Override
    101                 public void run() {
    102 
    103                     listener.onSuccess(pos, d);
    104 
    105                 }
    106             });
    107 
    108         } catch (final IOException e) {
    109             e.printStackTrace();
    110             // 进行错误信息回报
    111             handler.post(new Runnable() {
    112 
    113                 @Override
    114                 public void run() {
    115 
    116                     listener.onFail(e.getMessage());
    117 
    118                 }
    119             });
    120 
    121         }
    122 
    123     }
    124 
    125     /**
    126      * 获取网路图片资源
    127      * 
    128      * @param url
    129      * @return
    130      * @throws IOException
    131      */
    132     private static Drawable loadImgFromUrl(String urlStr) throws IOException {
    133         System.out.println("urlStr->" + urlStr);
    134         URL url;
    135         InputStream i = null;
    136         url = new URL(urlStr);
    137         i = (InputStream) url.getContent();
    138         Drawable drawable = Drawable.createFromStream(i, "img");
    139 
    140         return drawable;
    141 
    142     }
    143 
    144 }
    要想更新界面上内容,就必须在UI线程中去更新,所以就采用handler.post方法,post里面Runnable中
    run执行的代码其实是在UI线程中执行的,所以就符合android的规矩,才能进行更新
     
     
     
    参考文章:http://blog.csdn.net/harvic880925/article/details/17766027#t7
    源码下载:下载
  • 相关阅读:
    RAID磁盘阵列详解以及软RAID的实施部署
    Ubuntu 安装 配置 Mysql
    Asp.net页面之间传递参数的几种方法
    asp.net中网页间传递参数用什么方法比较
    Asp.net页面之间传递参数的几种方法
    asp.net中网页间传递参数用什么方法比较
    Asp.net页面之间传递参数的几种方法
    asp.net中网页间传递参数用什么方法比较
    CSS2.0中最常用的18条技巧
    Asp.net页面之间传递参数的几种方法
  • 原文地址:https://www.cnblogs.com/liangstudyhome/p/4631657.html
Copyright © 2020-2023  润新知