AsyncTask实现ListView中异步加载网络图片

本文探讨了在Android应用中加载网络图片时遇到的内存溢出(OOM)问题,并提供了一种解决方案。通过使用自定义的BaseAdapter和ImageLoad类,结合缓存机制和异步加载技术,有效地减少了内存占用,提高了图片加载效率。

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

近几天实现加载网络图片,中途遇到好多bug,其中最令人头疼的便是OOM超内存的bug,现在还是没能解决。可能的原因就是加载的网络图片超出手机内存。

这只能改变图片自身的大小,或者使用缩略图处理的方式了 。不过缩略图我还没有了解,希望大神看到后可以指点一二。

下面就是listView中加载网络图片等信息的部分核心源码。

myBaseAdapter.java文件

package com.iyoutingche.android.bean;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.iyoutingche.android.image.ImageLoad;
import com.zhy.weixin6.ui.R;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class myBaseAdapter extends BaseAdapter implements AbsListView.OnScrollListener {

    private LayoutInflater mInflater;
    private ImageLoad mImageLoad;
    private int mStart,mEnd;
    public static String[] URLS;    //保存所有url地址
    boolean mFirst;
 
    private List<HashMap<String, String>> data = new ArrayList<HashMap<String,String>>();
    private String url = null;// 存放图片的URL地址

    //data:从网络获的数据
    //resource:布局文件的id
    //from:map中的view值
    //to:布局文件中的id
    public myBaseAdapter(Context context, List<HashMap<String, String>> data,ListView listview) {
        mInflater = LayoutInflater.from(context);
        this.data = data;
        mFirst = true;
        mImageLoad=new ImageLoad(listview);  //保证创建一个ImageLoad对象
        URLS = new String[data.size()];
        Log.i("urlsize-----", data.size()+"");
        listview.setOnScrollListener(this);
        for(int i=0;i<data.size();i++){
            URLS[i] =  data.get(i).get("img").toString();
        }
    }

    public int getCount() {
        return data.size();
    }

    @Override
    public Object getItem(int position) {
        return data.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @SuppressLint("ViewHolder")
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHodler hodler = null;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.listview_item, parent, false);
            hodler = new ViewHodler();
            hodler.pcar_name = (TextView) convertView
                    .findViewById(R.id.item_name);
            hodler.pcar_number = (TextView) convertView
                    .findViewById(R.id.item_number);
            hodler.pcar_from = (TextView) convertView
                    .findViewById(R.id.item_from);
            hodler.depot_count = (TextView)convertView
                    .findViewById(R.id.item_depotCount);
            hodler.pcar_img = (ImageView) convertView.findViewById(R.id.item_img);
            convertView.setTag(hodler);        //将convertView与ViewHold创建联系
        }else{
            hodler = (ViewHodler) convertView.getTag();       //如果convertView不为空,直接得到viewHold的信息就行了。
        }
        hodler.pcar_name.setText(data.get(position).get("name").toString());
        hodler.pcar_number.setText("剩"+data.get(position).get("number").toString());
        hodler.pcar_from.setText("地址:"+data.get(position).get("from").toString());
        hodler.depot_count.setText("共"+data.get(position).get("depot_count").toString());
        //异步加载图片
        url = data.get(position).get("img").toString();
        mImageLoad.showImageByAsyncTask(hodler.pcar_img, url);
        hodler.pcar_img.setTag(url);
//        new ImageLoad().showImageByThread(hodler.pcar_img, url);
        return convertView;
    }
    
    class ViewHodler {
        TextView pcar_name;// 停车场名称
        TextView pcar_number;// 剩余空车位
        TextView pcar_from;// 停车场位置
        ImageView pcar_img;// 停车场的图片
        TextView depot_count; //停车场总车位
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if(mEnd >data.size()){
            Log.i("--------越界了吗?", mEnd+"");
            mImageLoad.cancelAllTasks();
            return;
        }
        if(scrollState == SCROLL_STATE_IDLE){  //如果是停止状态
            //加载所有项
            Log.i("值", "开始"+mStart+",结束"+mEnd);
            mImageLoad.loadImages(mStart, mEnd);
        }else{
            //停止加载
            mImageLoad.cancelAllTasks();
        }
    }
//每次都会调用该方法
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        mStart = firstVisibleItem;
        mEnd = firstVisibleItem + visibleItemCount;
        Log.i("索引-----", "开始"+mStart+",结束"+mEnd);
        //第一次显示时,调用。
        if(mFirst && visibleItemCount >0){
            mImageLoad.loadImages(mStart, mEnd);
            mFirst = false;
        }
    }
}

ImageLode.java文件

package com.iyoutingche.android.image;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;

import com.iyoutingche.android.bean.myBaseAdapter;
import com.zhy.weixin6.ui.R;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.util.Log;
import android.widget.ImageView;
import android.widget.ListView;

public class ImageLoad {
    
    //创建cache
    private LruCache<String, Bitmap> mCaches;
    private ListView mListView;
    private Set<PcarAsyncTask> mTask;
    
    public ImageLoad(ListView listview) {
        mListView = listview;
        mTask = new HashSet<PcarAsyncTask>();
        //获取最大缓存
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        int cacheSize = maxMemory / 4;
        mCaches = new LruCache<String, Bitmap>(cacheSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                //每次存入缓存时调用
                return value.getByteCount();
            }
        };
    }
    //增加到缓存
    public void addBitmapToCache(String url,Bitmap bitmap) {
        if(getBitmapFromCache(url) == null){   //校验当前缓存是否存在
            mCaches.put(url, bitmap);
        }
    }
    //获取缓存
    public Bitmap getBitmapFromCache(String url){   //将Lru理解成map集合,用get方法获得key对应的value。
        return mCaches.get(url);
    }
//    //通过Handler 将传递bitmap图片 为主线程更新UI
//    private Handler mHandler = new Handler(){
//        public void handleMessage(android.os.Message msg) {
//            if(mImageView.getTag().equals(mUrl)){
//                mImageView.setImageBitmap((Bitmap) msg.obj);
//            }
//        };    
//    };
    
    public Bitmap bitmapFromUrl(String urlString){
    Bitmap bitmap;
    InputStream is = null;
    try {
        URL url = new URL(urlString);   //将string类型的url转换成URL类型
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        //通过inputStream对象 解析成bitmap
        is = new BufferedInputStream(connection.getInputStream());
        bitmap = BitmapFactory.decodeStream(is);
        //释放connection连接
        connection.disconnect();
        return bitmap;
    } catch (IOException e) {
        e.printStackTrace();
    }finally{
        try {
            is.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    return null;
}
    //采用AsyncTask 方法加载图片
    public void showImageByAsyncTask(ImageView imageView , String url){
        //从缓存中获取图片
        Bitmap bitmap = getBitmapFromCache(url);
        //缓存中不存在,就重新加载
        if(bitmap == null){
//            new PcarAsyncTask(url).execute(url);
            imageView.setImageResource(R.drawable.actionbar_add_icon);   //未加载图片前,默认加载本地的图片
            Log.i("-------初次", "初次加载");
        }else{
            imageView.setImageBitmap(bitmap);
            Log.i("-------以后加载", "再次加载");
        }
    }
    private class PcarAsyncTask extends AsyncTask<String,Void, Bitmap>{
        private String mUrl;
//        private  ImageView mImageView;
        //建立构造方法,初始化imageview
        public PcarAsyncTask(String url) {
            mUrl = url;
        }
        //实现异步加载图片
        @Override
        protected Bitmap doInBackground(String... params) {
            String url = params[0];
            //从网络上获取图片
            Bitmap bitmap = bitmapFromUrl(url);
            if(bitmap != null){
                //将不再缓存的图片加入缓存
                addBitmapToCache(url, bitmap);
            }
            return bitmap;
        }
        //在imageView中设置bitmap参数
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            ImageView imageView = (ImageView) mListView.findViewWithTag(mUrl);
            if(imageView != null && bitmap != null){
                imageView.setImageBitmap(bitmap);
            }
            mTask.remove(this);
        }
    }
    //从网络中加载从start到end到缓存中
    public void loadImages(int start ,int end){
        for(int i = start ;  i<=end ;i++ ){
            String url = myBaseAdapter.URLS[i];
            
            //从缓存中获取图片
            Bitmap bitmap = getBitmapFromCache(url);
            //缓存中不存在,就重新加载
            if(bitmap == null){
                PcarAsyncTask task = new PcarAsyncTask(url);
//                new PcarAsyncTask(url).execute(url);
                task.execute(url);
                mTask.add(task);
            }else{
                ImageView imageView = (ImageView) mListView.findViewWithTag(url);
                imageView.setImageBitmap(bitmap);
            }
        }
    }
    //取消所有任务
    public void cancelAllTasks() {
        if(mTask != null){
            for (PcarAsyncTask task : mTask) {
                task.cancel(false);
            }
        }
    }
//    
//        //使用多线程进行一步加载
//    public void showImageByThread(ImageView imageview , final String url) {
//        mImageView = imageview;
//        mUrl = url;
//        new Thread(){
//            public void run() {
//                super.run();
//                Bitmap bitmap = bitmapFromUrl(url);
//                Message message = Message.obtain();   //重复利用message发送信息,节约资源。
//                message.obj = bitmap;
//                mHandler.sendMessage(message);    //发送message
//            };
//        }.start();
//    }
//    public Bitmap bitmapFromUrl(String urlString){
//        Bitmap bitmap;
//        InputStream is = null;
//        try {
//            URL url = new URL(urlString);   //将string类型的url转换成URL类型
//            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//            //通过inputStream对象 解析成bitmap
//            is = new BufferedInputStream(connection.getInputStream());
//            bitmap = BitmapFactory.decodeStream(is);
//            //释放connection连接
//            connection.disconnect();
//            return bitmap;
//        } catch (IOException e) {
//            e.printStackTrace();
//        }finally{
//            try {
//                is.close();
//            } catch (IOException e) {
//                // TODO Auto-generated catch block
//                e.printStackTrace();
//            }
//        }
//        return null;
//    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值