listview异步加载图片

这篇博客介绍了如何在Android中实现ListView的图片异步加载。通过自定义Adapter和利用AsyncImageTask类,实现网络图片的下载并缓存到内存和SD卡,解决了滑动时的卡顿问题,确保了良好的用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一般,我们使用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);然后在空闲的状态下调用异步加载图片。

这样就完成了异步加载,与滑动不加载的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值