android使用LruCache对listview加载图片时候优化处理

注意:LruCache是有版本限制的,低版本的sdk需要在libs文件夹添加相应的support-4v文件。
本文改造的大部分是参考http://www.iteye.com/topic/1118828,感谢。
不废话直接上工程代码,内有关键注释,项目就不上传了,自己对照着上面网址改呗。

首先是Application文件,负责创建图片存储文件夹:

public class MyApp extends Application{
    @Override
    public void onCreate() {
        super.onCreate();
        File f = new File(Environment.getExternalStorageDirectory()+"/TestSyncListView/pic/");
        if (!f.exists()) {
            f.mkdirs();
        }
    }
}

图像读取工具类:

?

public class SyncImageLoaderUtil
{

    private Object
lock =
new Object(); 

       

    private boolean mAllowLoad
=
true

   

    private boolean firstLoad
=
true

   

    private int mStartLoadLimit
=
0

   

    private int mStopLoadLimit
=
0

   

    final Handler
handler =
new Handler(); 

   

//   
private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>(); 

   

    private LruCache<String,Bitmap>
mMemoryCache;

     

    RunInOtherThread
runInOutherThread; 

   

    public SyncImageLoaderUtil(Context
context) { 

        super(); 

         

        int memClass
= ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();

        int cacheSize
=
1024 *1024 *memClass
/
8;

        mMemoryCache
=
new LruCache<String,
Bitmap>(cacheSize){

            @Override

            protected int sizeOf(String
key, Bitmap value) {

                //
TODO Auto-generated method stub

                return value.getRowBytes();

            }

        };

         

        runInOutherThread
=
new RunInOtherThread(); 

        runInOutherThread.start(); 

    

   

    public interface OnImageLoadListener

        public void onImageLoad(Integer
t, Drawable drawable); 

   

        public void onError(Integer
t); 

    

   

    public void setLoadLimit(int startLoadLimit,int stopLoadLimit)

        if (startLoadLimit
> stopLoadLimit) { 

//         
LogUtil.i("test", startLoadLimit+"--错误---"+stopLoadLimit);

            return

        

        mStartLoadLimit
= startLoadLimit; 

        mStopLoadLimit
= stopLoadLimit; 

    

   

    public void restore()

        mAllowLoad
=
true

        firstLoad
=
true

    

   

    public void lock()

        mAllowLoad
=
false

        firstLoad
=
false

    

   

    public void unlock()

        mAllowLoad
=
true

        synchronized (lock)

            lock.notifyAll(); 

        

    

   

    public void loadImage(Integer
t, String imageUrl, 

            OnImageLoadListener
listener) { 

        final OnImageLoadListener
mListener = listener; 

        final String
mImageUrl = imageUrl; 

        final Integer
mt = t; 

           

        runInOutherThread.getHandler().post(new Runnable()

   

            @Override 

            public void run()

                if (!mAllowLoad)

                    synchronized (lock)

                        try 

                            lock.wait(); 

                        }catch (InterruptedException
e) { 

                            //
TODO Auto-generated catch block 

                            e.printStackTrace(); 

                        

                    

                

                   

                if (mAllowLoad
&& firstLoad) { 

                    loadImage(mImageUrl,
mt, mListener); 

                

   

//               
LogUtil.e("test", "原始开始:"+mStartLoadLimit+"原始当前位置:"+mt+"原始结束:"+mStopLoadLimit);

                if (mAllowLoad
&& mt <= mStopLoadLimit && mt >= mStartLoadLimit) { 

//                 
LogUtil.e("test", "开始:"+mStartLoadLimit+"当前位置:"+mt+"结束:"+mStopLoadLimit);

                    loadImage(mImageUrl,
mt, mListener);

                

            

   

        }); 

    

       

    private void loadImage(final String
mImageUrl,
final Integer
mt, 

            final OnImageLoadListener
mListener) { 

   

        if (mImageUrl!=null &&
mMemoryCache.get(mImageUrl)!=
null)

//           
SoftReference<Drawable> softReference = imageCache.get(mImageUrl); 

            final Drawable
d =
new BitmapDrawable(mMemoryCache.get(mImageUrl)); 

//           
LogUtil.d("ppp", "drawable:"+d);

            if (d
!=
null)

                handler.post(new Runnable()

                    @Override 

                    public void run()

                        if (mAllowLoad)

                            mListener.onImageLoad(mt,
d); 

                        

                    

                }); 

                return

            

        

        try 

            final Drawable
d = loadImageFromUrl(mImageUrl); 

            if (d
!=
null)

                mMemoryCache.put(mImageUrl,
((BitmapDrawable)d).getBitmap());

            

            handler.post(new Runnable()

                @Override 

                public void run()

                    if (mAllowLoad)

                        mListener.onImageLoad(mt,
d); 

                    

                

            }); 

        }catch (IOException
e) { 

            handler.post(new Runnable()

                @Override 

                public void run()

                    mListener.onError(mt); 

                

            }); 

            e.printStackTrace(); 

        

    

   

    public static Drawable
loadImageFromUrl(String url)
throws IOException

        //DebugUtil.debug(url); 

        if (Environment.getExternalStorageState().equals( 

                Environment.MEDIA_MOUNTED))

            File
f =
new File(Environment.getExternalStorageDirectory() 

                    +"/Weiyu/pic/" +
MD5Util.getMD5(url.getBytes())); 

            if (f.exists())

                FileInputStream
fis =
new FileInputStream(f); 

                Drawable
d = Drawable.createFromStream(fis,
"src"); 

                return d; 

            

            URL
m =
new URL(url); 

            InputStream
i = (InputStream) m.getContent(); 

            DataInputStream
in =
new DataInputStream(i); 

            FileOutputStream
out =
new FileOutputStream(f); 

            byte[]
buffer =
new byte[1024]; 

            int byteread
=
0

            while ((byteread
= in.read(buffer)) != -
1)

                out.write(buffer,0,
byteread); 

            

            

            in.close(); 

            out.close();

            return loadImageFromUrl(url); 

        }else 

            URL
m =
new URL(url); 

            InputStream
i = (InputStream) m.getContent(); 

            Drawable
d = Drawable.createFromStream(i,
"src"); 

            return d; 

        

   

    

}

  
线程辅助类:

?

public class RunInOtherThread
{

    private static final String
LOG_TAG =
"RunInOtherThread"

     

    private LooperThread
localThread =
new LooperThread(); 

       

    private boolean isRunning
=
true

   

    public Handler
getHandler(){ 

        return localThread.getHandler(); 

    

       

    private class LooperThreadextends Thread

        private Handler
mHandler; 

   

        public void run()

            Looper.prepare(); 

            mHandler
=
new Handler()

                public void handleMessage(Message
msg) { 

                    onReceiveMessage(msg.what); 

                

            }; 

            Looper.loop(); 

        

           

        Handler
getHandler(){ 

            return mHandler; 

        

      

    

       

    public void start(){ 

        localThread.start(); 

    

       

    public void quit(){ 

        localThread.getHandler().getLooper().quit(); 

    

       

    public void sendMessage(int what){ 

        getHandler().sendEmptyMessage(what); 

    

       

    public Thread
getThread(){ 

        return localThread; 

    

       

    public void onReceiveMessage(int what){};

}

  
使用类:

?

//
实例化工具类

SyncImageLoaderUtil
syncImageLoader =
new SyncImageLoaderUtil(mContext);

 

syncImageLoader.loadImage(position,
model.mPic, imageLoadListener);
//应用接口:参数一是加载图片的位置;参数二是加载的ImageView;参数三是回调接口

 

//
map保存的键是位置,值是listview对应位置的布局

HashMap
map =
new HashMap();

map.put(position,
convertView);

 

SyncImageLoaderUtil.OnImageLoadListener
imageLoadListener =
new SyncImageLoaderUtil.OnImageLoadListener()
{

 

        @Override

        public void onImageLoad(Integer
t, Drawable drawable) {

            View
view = (View) map.get(t);

            if (view
!=
null)
{

                ImageView
iv = (ImageView) view.findViewById(R.id.image);

                iv.setBackgroundDrawable(drawable);

            }

        }

 

        @Override

        public void onError(Integer
t) {

                        //
图片加载失败

                       //
取得listview对应的位置的行的内容布局

                    MusicModel
model = (MusicModel) getItem(t);

            View
view = mListView.findViewWithTag(model);

            if (view
!=
null)
{

                ImageView
iv = (ImageView) view.findViewById(R.id.image);

                iv.setBackgroundResource(R.drawable.img_pic);

            }

        }

 

    };

 

 

//
实现类而且需要实现OnScrollListener接口

public void loadImage()
{

                //
不要在这里使用listview的getFirstVisiblePosition方法,位置不准

        if (end
>= getCount()) {

            end
= getCount() -
1;

        }

        syncImageLoader.setLoadLimit(start,
end);

        syncImageLoader.unlock();

    }

 

    @Override

    public void onScrollStateChanged(AbsListView
view,
int scrollState)
{

        //
TODO Auto-generated method stub

        if (lodingView)
{

            switch (scrollState)
{

            case AbsListView.OnScrollListener.SCROLL_STATE_FLING:

                syncImageLoader.lock();

                break;

            case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:

 

                loadImage();

                break;

            case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:

                syncImageLoader.lock();

                break;

            default:

                break;

            }

        }

    }

 

    @Override

    public void onScroll(AbsListView
view,
int firstVisibleItem,

            int visibleItemCount,int totalItemCount)
{

        //
在这里取得的位置较准确,不过也会出现特殊的奇疤机型是不行的

                //
start与end是定义的变量

        start
= firstVisibleItem;

        end
= firstVisibleItem + visibleItemCount;

        if (firstVisibleItem
!=
0)
{

                        //
lodingView是控制变量,用来控制第一次进来视图加载读取图片

            lodingView
=
true;

        }else {

            lodingView
=
false;

            loadImage();

        }

    }

时间: 2024-08-30 10:02:42

android使用LruCache对listview加载图片时候优化处理的相关文章

Android编程学习之异步加载图片的方法_Android

本文实例讲述了Android编程学习之异步加载图片的方法.分享给大家供大家参考,具体如下: 最近在android开发中碰到比较棘手的问题,就是加载图片内存溢出.我开发的是一个新闻应用,应用中用到大量的图片,一个界面中可能会有上百张图片.开发android应用的朋友可能或多或少碰到加载图片内存溢出问题,一般情况下,加载一张大图就会导致内存溢出,同样,加载多张图片内存溢出的概率也很高. 列一下网络上查到的一般做法: 1.使用BitmapFactory.Options对图片进行压缩 2.优化加载图片的

scollview内嵌套listview加载图片时显示在了listview上。

问题描述 scollview内嵌套listview加载图片时显示在了listview上. 我的scollview里面有imageview.和listview,listview加载图片完成 之后只显示listview,而imageview被翻到了上面,需要手动滑下来才看得见. 请教各位大神帮我解决下. 解决方案 加载完后,延时滚动到顶部. scrollView.postDelayed(new Runnable() { @Override public void run() { scrollView

Android使用控件ImageView加载图片的方法_Android

在 Android 加载图片一般使用 ImageView,这里简单记录一下这个控件的使用方法. 最简单就是在 xml 里直接使用 ImageView 标签: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="

Listview加载的性能优化是如何实现的_Android

在android开发中Listview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容,用户可以自由的定义listview每一列的布局,但当listview有大量的数据需要加载的时候,会占据大量内存,影响性能,这时候就需要按需填充并重新使用view来减少对象的创建. listview加载的核心是其adapter,本文针对listview加载的性能优化就是对adpter的优化,总共分四个层次: 0.最原始的加载 1.利用convertView 2.利用ViewHolder 3.实现

Listview加载的性能优化是如何实现的

在android开发中Listview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容,用户可以自由的定义listview每一列的布局,但当listview有大量的数据需要加载的时候,会占据大量内存,影响性能,这时候就需要按需填充并重新使用view来减少对象的创建. listview加载的核心是其adapter,本文针对listview加载的性能优化就是对adpter的优化,总共分四个层次: 0.最原始的加载 1.利用convertView 2.利用ViewHolder 3.实现

Android App中使用Glide加载图片的教程_Android

与其他图片加载库相同,Glide除了可以加载网络图片之外,也可以加载本地图片.甚至还可以从各种各样奇葩的数据源中加载图片. 加载网络图片很多情况下,我们使用图片加载库就是为了加载网络图片.网络操作是一个很复杂的东西.试想一下,如果没有图片加载库,我们就要手动去下载图片,缓存图片,最后再从文件里面读取bitmap并设置到Imageview里面.这还算好的,要是在Listview里面你会更头疼的.原因我就不说了,你懂的~~再加上各种各样的Bitmap操作,保准你再也不想撸代码了.而且Bitmap这东

Android App中使用Glide加载图片的教程

与其他图片加载库相同,Glide除了可以加载网络图片之外,也可以加载本地图片.甚至还可以从各种各样奇葩的数据源中加载图片. 加载网络图片 很多情况下,我们使用图片加载库就是为了加载网络图片.网络操作是一个很复杂的东西.试想一下,如果没有图片加载库,我们就要手动去下载图片,缓存图片,最后再从文件里面读取bitmap并设置到Imageview里面.这还算好的,要是在Listview里面你会更头疼的.原因我就不说了,你懂的~~再加上各种各样的Bitmap操作,保准你再也不想撸代码了.而且Bitmap这

基于android示例程序(bitmapfun) 高效加载图片让人无语地方_Android

在android的开发指南上有这样一篇文章,如何更有效率的加载图片,地址为 https://developer.android.com/training/displaying-bitmaps/index.html,这篇文章详细地介绍了如何加载高清图到内存,同时避免系统报OOM的问题,文章写得很不错,示例程序也可以直接运行.在我们项目的一次小版本升级的过程中,我们尝试了使用git上的一个开源项目afinal(bitmapfun的封装版)来加载图片,但是在测试的时候发现了一个问题,新的图片加载器(b

关于ANDROID示例程序(BITMAPFUN)——高效加载图片的坑爹地方

下面的都是费话,不想看的,直接看红色字体,然后自己实验下 在android的开发指南上有这样一篇文章,如何更有效率的加载图片,地址为 https://developer.android.com/training/displaying-bitmaps/index.html,这篇文章详细地介绍了如何加载高清图到内存,同时避免系统报OOM的问题,文章写得很不错,示例程序也可以直接运行.在我们项目的一次小版本升级的过程中,我们尝试了使用git上的一个开源项目afinal(bitmapfun的封装版)来加