ListView에 아래 그림과 같이 AlbumArt(thumbnail)을 표시하는데
빠른 스크롤시에도 지연 현상이 없도록 AsyncTask를 이용한다.
최초 반응성이 많이 늦어지만 AsyncTask를 사용하므로써 1차적으로 많이 개선되었다.
(참고 자료 :http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/)
Source
class ViewHolder {
public long albumId;
public TextView tvTitle;
public TextView tvArtist;
public TextView tvDuration;
public ImageView ivAlbumArt;
}
ViewHolder에 albumArt를 구분할수 있는 albumId 필드를 추가한다.
long albumId = cursor.getLong(cursor
.getColumnIndex(android.provider.MediaStore.Audio.Media.ALBUM_ID));
holder.albumId = albumId;
new ThumbnailTask(albumId, holder).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, getActivity());
CursorAdapter의 bindView 구문에서 albumId 값을 가져와 AsyncTask를 상속받아서 구현한
ThumbnailTask 객체의 생성자로 넘겨준다.
*중요 executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, getActivity());
첫번째 인자 AsyncTask.SERIAL_EXECUTOR 는 해당 ThumbnailTask가 싱글 Thread로 동작함을 의미한다.
AsyncTask.THREAD_POOL_EXECUTOR로 바꿔주면 병렬 Thread로 동작하나 오류가 빈번하게 발생된다. 병렬 Thread로 구현을 하려면 더 많은 것을 고려해야한다. 그래서 이부분에서는 생략한다.
싱글 Thread도 실사용엔 크게 문제가 없을 만큼 동작된다.[단 빠른 Scroll시 지연현상이 조금 발생된다.)
class ThumbnailTask extends AsyncTask<Context, Integer, Bitmap> {
private long mAlbumId;
private ViewHolder mHolder;
public ThumbnailTask(long albumId, ViewHolder holder) {
mAlbumId = albumId;
mHolder = holder;
}
@Override
protected Bitmap doInBackground(Context... params) {
Bitmap bitmap = null;
if (mHolder.albumId == mAlbumId) {
Uri sArtworkUri = Uri
.parse("content://media/external/audio/albumart");
Uri sAlbumArtUri = ContentUris.withAppendedId(sArtworkUri, mAlbumId);
try {
ParcelFileDescriptor fd = params[0].getContentResolver()
.openFileDescriptor(sAlbumArtUri, "r");
bitmap = BitmapFactory.decodeFileDescriptor(
fd.getFileDescriptor(), null, null);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
this.cancel(isCancelled());
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (mHolder.albumId == mAlbumId) {
if(null!=bitmap){
mHolder.ivAlbumArt.setImageBitmap(bitmap);
}
} else {
this.cancel(isCancelled());
}
}
}
생성자에서 넘겨받은 albumId와 ViewHolder개체를 사용하여 ViewHolder의 albumId와 같은 경우만
현재 화면에 나타나고 있다고 판단하여 bitmap을 ImageView 넣어주는 작업을 한다.
Scroll 시 ViewHolder 객체는 재 사용되기 때문에 ThumbnailTask 개체 albumId값은 화면에 표시되어야 하는 albumId로 바뀐다. 그러므로 생성자에서 전달받은 albumId와 ViewHolder의 albumId를 비교 하므로서 AlbumArt가 화면상에서 필요한지 확인 할수 있다.
'PROGRAMING > Android' 카테고리의 다른 글
listView 항목에 Audio Albumart(thumbnail)을 지연 없이 나타내기 LinkedHashMap과 SoftReference사용 [캐시 처리] (1) | 2013.02.24 |
---|---|
listView 항목에 Audio Albumart(thumbnail)을 지연 없이 나타내기 AsyncTask 호출 늦게 하기 (0) | 2013.02.23 |
Audio AlbumArt 가져오기. (0) | 2013.02.22 |
android.content.CursorLoader 와 LoaderCallbacks 인터페이스 (0) | 2013.02.22 |
[widget]android.widget.CursorAdapter, ViewHolder pattern (0) | 2013.02.19 |