利用LruCache为GridView加载大量本地图片完整示例

MainActivity如下:

package cc.testlrucache;

import android.os.Bundle;
import android.widget.GridView;
import android.app.Activity;

public class MainActivity extends Activity {
    private GridView mGridView;
    private GridViewAdapter mGridViewAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        init();
    }

    private void init(){
        mGridView = (GridView) findViewById(R.id.gridView);
        mGridViewAdapter = new GridViewAdapter(this, 0, ImagesPath.IMAGES_PATH, mGridView);
        mGridView.setAdapter(mGridViewAdapter);
    }

}

GridViewAdapter如下:

package cc.testlrucache;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v4.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.AbsListView.OnScrollListener;
/**
 *   LruCache的流程分析:
 *
 *   从第一次进入应用的情况下开始
 * 1 依据图片的Path从LruCache缓存中取图片.
 *   若图片存在缓存中,则显示该图片;否则显示默认图片
 * 2 因为是第一次进入该界面所以会执行:
 *   loadBitmaps(firstVisibleItem, visibleItemCount);
 *
 *   从loadBitmaps()方法作为切入点,继续往下梳理
 *
 * 3 尝试从LruCache缓存中取图片.如果在显示即可,否则进入4
 * 4 从SDCrad读取图片,并且将读取后的图片保存到LruCache缓存中
 *
 * 5 在停止滑动时,会调用loadBitmaps(firstVisibleItem, visibleItemCount)
 *   显示目前GridView可见Item的图片
 */
public class GridViewAdapter extends ArrayAdapter<String> {
    private GridView mGridView;
    //图片缓存类
    private LruCache<String, Bitmap> mLruCache;
    //GridView中可见的第一张图片的下标
    private int mFirstVisibleItem;
    //GridView中可见的图片的数量
    private int mVisibleItemCount;
    //记录是否是第一次进入该界面
    private boolean isFirstEnterThisActivity = true;

    public GridViewAdapter(Context context, int textViewResourceId,String[] objects, GridView gridView) {
        super(context, textViewResourceId, objects);
        mGridView = gridView;
        mGridView.setOnScrollListener(new ScrollListenerImpl());
        //应用程序最大可用内存
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        //设置图片缓存大小为maxMemory的1/3
        int cacheSize = maxMemory/3;

        mLruCache = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                return bitmap.getRowBytes() * bitmap.getHeight();
            }
        };

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        String path = getItem(position);
        View view;
        if (convertView == null) {
            view = LayoutInflater.from(getContext()).inflate(R.layout.gridview_item, null);
        } else {
            view = convertView;
        }
        ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
        //为该ImageView设置一个Tag,防止图片错位
        imageView.setTag(path);
        //为该ImageView设置显示的图片
        setImageForImageView(path, imageView);
        return view;
    }

    /**
     * 为ImageView设置图片(Image)
     * 1 从缓存中获取图片
     * 2 若图片不在缓存中则为其设置默认图片
     */
    private void setImageForImageView(String imagePath, ImageView imageView) {
        Bitmap bitmap = getBitmapFromLruCache(imagePath);
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap);
        } else {
            imageView.setImageResource(R.drawable.default_image);
        }
    }

    /**
     * 将图片存储到LruCache
     */
    public void addBitmapToLruCache(String key, Bitmap bitmap) {
        if (getBitmapFromLruCache(key) == null) {
            mLruCache.put(key, bitmap);
        }
    }

    /**
     * 从LruCache缓存获取图片
     */
    public Bitmap getBitmapFromLruCache(String key) {
        return mLruCache.get(key);
    }

   /**
    * 为GridView的item加载图片
    * @param firstVisibleItem GridView中可见的第一张图片的下标
    * @param visibleItemCount GridView中可见的图片的数量
    */
    private void loadBitmaps(int firstVisibleItem, int visibleItemCount) {
        try {
            for (int i = firstVisibleItem; i < firstVisibleItem + visibleItemCount; i++) {
                String imagePath = ImagesPath.IMAGES_PATH[i];
                Bitmap bitmap = getBitmapFromLruCache(imagePath);
                if (bitmap == null) {
                    System.out.println("--->XXXXX 图片"+imagePath+"不在缓存中"+",所以从SDCard读取");
                    bitmap=BitmapFactory.decodeFile(imagePath);
                    ImageView imageView = (ImageView) mGridView.findViewWithTag(imagePath);
                    if (imageView != null && bitmap != null) {
                        imageView.setImageBitmap(bitmap);
                    }
                    //将从SDCard读取的图片添加到LruCache中
                    addBitmapToLruCache(imagePath, bitmap);
                } else {
                    System.out.println("--->OOOOO 图片在缓存中="+imagePath+",从缓存中取出即可");
                    //依据Tag找到对应的ImageView显示图片
                    ImageView imageView = (ImageView) mGridView.findViewWithTag(imagePath);
                    if (imageView != null && bitmap != null) {
                        imageView.setImageBitmap(bitmap);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private class ScrollListenerImpl implements OnScrollListener{
        /**
         * 通过onScrollStateChanged获知:每次GridView停止滑动时加载图片
         * 但是存在一个特殊情况:
         * 当第一次入应用的时候,此时并没有滑动屏幕的操作即不会调用onScrollStateChanged,但应该加载图片.
         * 所以在此处做一个特殊的处理.
         * 即代码:
         * if (isFirstEnterThisActivity && visibleItemCount > 0) {
         *      loadBitmaps(firstVisibleItem, visibleItemCount);
         *      isFirstEnterThisActivity = false;
         *    }
         *
         * ------------------------------------------------------------
         *
         * 其余的都是正常情况.
         * 所以我们需要不断保存:firstVisibleItem和visibleItemCount
         * 从而便于中在onScrollStateChanged()判断当停止滑动时加载图片
         *
         */
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
            mFirstVisibleItem = firstVisibleItem;
            mVisibleItemCount = visibleItemCount;
            if (isFirstEnterThisActivity && visibleItemCount > 0) {
                System.out.println("---> 第一次进入该界面");
                loadBitmaps(firstVisibleItem, visibleItemCount);
                isFirstEnterThisActivity = false;
            }
        }

        /**
         *  GridView停止滑动时下载图片
         *  其余情况下取消所有正在下载或者等待下载的任务
         */
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            if (scrollState == SCROLL_STATE_IDLE) {
                System.out.println("---> GridView停止滑动  mFirstVisibleItem="+mFirstVisibleItem+",mVisibleItemCount="+mVisibleItemCount);
                loadBitmaps(mFirstVisibleItem, mVisibleItemCount);
            }
        }
    }
}

ImagesPath如下:

package cc.testlrucache;

public class ImagesPath {

    public final static String DIR="/mnt/sdcard/Test/";
    public final static String[] IMAGES_PATH = new String[] {
        DIR+"a.jpg",
        DIR+"b.jpg",
        DIR+"c.jpg",
        DIR+"d.jpg",
        DIR+"e.jpg",
        DIR+"f.jpg",
        DIR+"g.jpg",
        DIR+"h.jpg",
        DIR+"i.jpg",
        DIR+"j.jpg",
        DIR+"k.jpg",
        DIR+"l.jpg",
        DIR+"m.jpg",
        DIR+"n.jpg",
        DIR+"o.jpg",
        DIR+"p.jpg",
        DIR+"q.jpg",
        DIR+"r.jpg",
        DIR+"s.jpg",
        DIR+"t.jpg",
        DIR+"w.jpg",
        DIR+"x.jpg",
        DIR+"y.jpg",
        DIR+"z.jpg",
        DIR+"za.jpg",
        DIR+"zb.jpg",
        DIR+"zc.jpg",
        DIR+"zd.jpg",
        DIR+"ze.jpg",
        DIR+"zf.jpg",
        DIR+"zg.jpg",
        DIR+"zh.jpg",
        DIR+"zi.jpg",
        DIR+"zj.jpg",
        DIR+"zk.jpg",
        DIR+"zl.jpg",
        DIR+"zm.jpg"
};
}

main.xml如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

   <GridView
       android:id="@+id/gridView"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       android:verticalSpacing="10dip"
       android:listSelector="@android:color/transparent"
       android:numColumns="3"
    />

</RelativeLayout>

gridview_item.xml如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="90dip"
        android:layout_height="90dip"
        android:src="@drawable/default_image"
        android:layout_centerInParent="true"
        />

</RelativeLayout>
时间: 2024-11-06 15:54:58

利用LruCache为GridView加载大量本地图片完整示例的相关文章

利用LruCache和DiskLruCache加载网络图片实现图片瀑布流效果(升级版)

MainActivity如下: package cc.patience7; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 采用瀑布流的形式加载大量网络图片 * 详细分析参见WaterfallScrollView * * 更新说明: * 在原本的的基础上添加了本地缓存DiskLruCache * * 所以在该示例中对于图片的缓存采用了:LruCache + DiskLruCache 的技术 * * 参考

利用LruCache加载网络图片实现图片瀑布流效果(改进版)

MainActivity如下: package cc.patience4; import cc.patience4.R; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 采用瀑布流的形式加载大量网络图片 * 详细分析参见WaterfallScrollView * * 更新说明: * 该示例在基础版的基础上加入了图片查看功能. * 点击瀑布流中一张图片后可欣赏图片并能对图片进行单指拖动和两指缩放. * 对

利用LruCache加载网络图片实现图片瀑布流效果(基础版)

MainActivity如下: package cc.patience3; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 采用瀑布流的形式加载大量网络图片 * 详细分析参见WaterfallScrollView * * 参考资料: * 1 http://blog.csdn.net/guolin_blog/article/details/10470797 * 2 http://blog.csdn.net

Android利用Volley异步加载数据(JSON和图片)完整示例

Android利用Volley异步加载数据(JSON和图片)完整示例 MainActivity.java package cc.testvolley; import org.json.JSONObject; import android.app.Activity; import android.app.ProgressDialog; import android.graphics.Bitmap; import android.os.Bundle; import android.support.v

Struts2的国际化(二)-利用超链接实现动态加载国际化资源文件

原理:程序是根据Locale来确定国际化资源文件,因此关键之处在于知道 Struts2 框架是如何确定 Local 对象的 ! 由于Struts2 使用 i18n 拦截器处理国际化,并且将其注册在默认的拦截器中,因此,可以通过阅读 I18N 拦截器知道. 具体确定 Locale 对象的过程: > Struts2 使用 i18n 拦截器 处理国际化,并且将其注册在默认的拦截器栈中 > i18n拦截器在执行Action方法前,自动查找请求中一个名为 request_locale 的参数. 如果该参

【转】GridView 加载空行并点击编辑每一个单元格

1 代码 2 3 <script runat="server"> 4 protectedvoid Button1_Click(object sender, System.EventArgs e) 5 { 6 GridView1.DataSource = GetData(); 7 GridView1.DataBind(); 8 } 9 10 protectedvoid Button2_Click(object sender, System.EventArgs e) 11 {

GridView加载大量图片卡顿问题

1  在异步加载之前的代码的和普通加载代码一样,只需要在GirdView的Adapter的public View getView(int position, View convertView, ViewGroupparent)方法使用异步加载的方式返回ImageView. 2  如果能把加载过的图片给缓存起来,而不用每次都从sd卡上读取,这样效率应该会提高不少.所以可以先建一个缓存类,MemoryCache,为了能尽可能缓存,又尽可能的不抛出OOM的异常,可以使用SoftReference<Bi

页面加载中的图片性能优化【转】

我的大部分性能优化工作都集中在JavaScript和CSS上,从早期的Move Scripts to the Bottom和Put Stylesheets at the Top规则.为了强调这些规则的重要性,我甚至说过,“JS和CSS是页面上最重要的部分”. 几个月后,我意识到这是错误的.图片才是页面上最重要的部分. 我关注JS和CSS的重点也是如何能够更快地下载图片.图片是用户可以直观看到的.他们并不会关注JS和CSS.确实,JS和CSS会影响图片内容 的展示,尤其是会影响图片的展示方式(比如

(四十二)、加载大分辨率图片到内存

有些图片的分辨率比较高,把它直接加载到手机内存中之后,会导致堆内存溢出的问题,下面就讲解一下Android的堆内存以及如何在Android应用中加载一个高分辨率的图片的方法. 1  还原堆内存溢出的错误首先来还原一下堆内存溢出的错误.首先在SD卡上放一张照片,分辨率为(3776 X 2520),大小为3.88MB,是我自己用相机拍的一张照片.应用的布局很简单,一个Button一个ImageView,然后按照常规的方式,使用BitmapFactory加载一张照片并使用一个ImageView展示.代