最近在做測試時,沒想到有個客戶很認真的測試了這個功能,他將手機裡的相簿塞了兩千多張照片,然後測 run了幾次,結果嘛在讀取縮圖時花了一些時間,畫面才開啟。
而用測試程式跑的結果,雖然畫面一下子就打開了,但是 .... 不幸福的事發生了,沒想到滑到一半程式就掛了。
看似在讀大量圖片時,記憶體緩存不足造成。
想辦法1:
先載入一部份照片,如果滑動到相簿底部時,再下載更多照片,好處是可以不需要載入所有的照片,節省更多的記憶。這個方法絕對是可行的,但每次要下載照片時,滑動就會卡卡的。
gridView.setOnScrollListener( new OnScrollListener() {
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (firstVisibleItem + visibleItemCount == totalItemCount) {
isScrollFoot = true;
} else {
isScrollFoot = false;
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
&& isScrollFoot) { // 滾動靜止且滾動到最底部
//讀取下20張照片的code
}
}
});
想辦法2:
讓畫面開啟後,照片每載入一部份(比如20張),再載入下20張,直到全部照片下載完畢。雖然這個方法並沒有節省到記憶體,但是我們在滑動時會比較順,但似乎拼命滑動時還是有可能掛掉。
// 非同步執行讀取相簿
private static final class AsyncReadPictures extends
AsyncTask<String[], Void, Boolean> {
private MainActivity context = null;
public AsyncReadPictures(MainActivity context) {
this. context = context;
}
@Override
protected Boolean doInBackground(String[]... params) {
// TODO Auto-generated method stub
int readedindex = context. index;
for ( int i = context. index; i < context. count; i++) {
if ( context. cursor.isClosed()) {
return null;
}
context. cursor.moveToPosition(i);
// context.logger.info("imagecursor moveToPosition:" + i);
// 取得照片的ID
int id = context. cursor.getInt( context. image_column_index); // id在table中第一行
int dataColumnIndex = context. cursor
.getColumnIndex(MediaStore.Images.Media. DATA);
// arrPath[i] = imagecursor.getString(dataColumnIndex); //
// 照片路徑(完整路徑),範例:/ mnt/sdcard /external_sd/DCIM/Camera/2013-03-25
String filepath = context. cursor.getString(dataColumnIndex); // 照片路徑(完整路徑),範例:/ mnt/sdcard /external_sd/DCIM/Camera/2013-03-25
// logger.info(i + " " + arrPath[i]); // 19.19.02.jpg
File file = new File(filepath);
if (file.exists() == false) {
// logger.info("file not exists");
continue;
} else {
// logger.info("file length space:" + file.length());
if (file.length() == 0) {
// logger.info("file length is 0:" + file.length());
continue;
}
}
context. thumbs.add( context. index, id + "");
context. imagePaths.add( context. index, filepath);
context. index++;
if ((readedindex + 20) == context. index) {
break;
}
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
// context.dialog.dismiss();
if (result != null) {
context. imageAdapter.notifyDataSetChanged();
if ( context. index < context. count) {
context.readNextPictures();
}
}
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
}
@Override
public void onDestroy() {
super.onDestroy();
if ( cursor != null) {
cursor.close();
}
}
public void readNextPictures() {
AsyncReadPictures async = new AsyncReadPictures(MainActivity.this );
async.execute();
}
以上兩種方法,看似有那麼些幫助,但是仍存記憶體緩存不足的問題。
在ImageAdapter裡填添一個help物件來存放view等相關物件,包含icon的bitmap,這樣一來滑動時可減少記憶體的浪費。
在ImageAdapter.java的getView()中,以下段code取代:
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context. LAYOUT_INFLATER_SERVICE );
View rowview = null;
ImageAdapterHolder holder;
ImageView imgview_photoItem_photo;
if (convertView == null) {
// 連結xml 中實體物件
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context. LAYOUT_INFLATER_SERVICE );
rowview = inflater.inflate(R.layout.listitem_photo, parent, false); // 設定list中Item的 xml
layout = (ViewGroup) rowview.findViewById(R.id.rl_photoItem);
imgview_photoItem_photo = (ImageView) rowview
.findViewById(R.id. img_photoItem_photo);
cb_photoItem_checkBox = (CheckBox) rowview
.findViewById(R.id. cb_photoItem_checkBox);
holder = new ImageAdapterHolder();
holder.setImgv_photoItem_photo(imgview_photoItem_photo);
holder.setLayout( layout);
layout.setTag(holder);
} else {
holder = ( ImageAdapterHolder) convertView.getTag();
layout = holder.getLayout();
imgview_photoItem_photo = holder.getImgv_photoItem_photo();
}
imgview_photoItem_photo.setId(position);
如此一來,滑動照片的流暢度更好了。
沒有留言:
張貼留言