編輯:關於Android編程
MainActivity如下:
package cc.testlrucache; import android.os.Bundle; import android.widget.GridView; import android.app.Activity; /** * Demo描述: * Android利用LruCache為GridView加載大量本地圖片完整示例,防止OOM * * 更多參考: * http://blog.csdn.net/lfdfhl */ 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{ private GridView mGridView; //圖片緩存類 private LruCache 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 (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如下:
gridview_item.xml如下:
Android有很多種drawable類型,除了前幾篇詳細講解的shape、selector、layer-list,還有上一篇提到的color、bitmap、
在android開發中ListView是比較常用的組件,它以列表的形式展示具體內容,並且能夠根據數據的長度自適應顯示。抽空把對ListView的使用做了整理,並寫了個小例
程序入口//// LCBusinessTableViewController.m// 口碑頁面//// Copyright ? 2016年 LongChuang.
本例子一種介紹了四種啟動方式來1老趕集網的啟動,效果圖 : 實現原理 :通過handler延時一段時間 向主線程發送一條跳轉界面的消息(這也是大部分啟動頁所用到的)代碼示