基类的onCreateMethod:
setListAdapter(new EfficientAdapter(this));
高效的基本适配器类:
private class EfficientAdapter extends BaseAdapter {
private LayoutInflater mInflater;
Friends obj;
Friends object;
FriendsPictures pictureObject;
ArrayList<FriendsPictures> arrayFriendsPictures;
public EfficientAdapter(Context context) {
// Cache the LayoutInflate to avoid asking for a new one each time.
mInflater = LayoutInflater.from(context);
}
/**
* The number of items in the list is determined by the number of speeches
* in our array.
*
* @see android.widget.ListAdapter#getCount()
*/
public int getCount() {
return arrFriendsObject.size();
}
/**
* Since the data comes from an array, just returning the index is
* sufficent to get at the data. If we were using a more complex data
* structure, we would return whatever object represents one row in the
* list.
*
* @see android.widget.ListAdapter#getItem(int)
*/
public Object getItem(int position) {
return position;
}
/**
* Use the array index as a unique id.
*
* @see android.widget.ListAdapter#getItemId(int)
*/
public long getItemId(int position) {
return position;
}
private final ImageDownloader imageDownloader = new ImageDownloader();
// private final DrawableManager drawable= new DrawableManager();
/**
* Make a view to hold each row.
*
* @see android.widget.ListAdapter#getView(int, android.view.View,
* android.view.ViewGroup)
*/
public View getView(int position, View convertView, ViewGroup parent) {
// A ViewHolder keeps references to children views to avoid unneccessary calls
// to findViewById() on each row.
final ViewHolder holder;
obj = arrFriendsObject.get(position);
// When convertView is not null, we can reuse it directly, there is no need
// to reinflate it. We only inflate a new View when the convertView supplied
// by ListView is null.
if (convertView == null) {
convertView = mInflater.inflate(R.layout.Friendslistview, null);
// Creates a ViewHolder and store references to the two children views
// we want to bind data to.
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.FriendsText);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the TextView
// and the ImageView.
holder = (ViewHolder) convertView.getTag();
}
// Bind the data efficiently with the holder.
holder.text.setText(obj.FriendsTitle);
// holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
// _mLoadImage = new GetImageAsyncTask();
// _mLoadImage.execute(urls[position]);
object = new Friends();
object = arrFriendsObject.get(position);
arrayFriendsPictures = new ArrayList<FriendsPictures>();
pictureObject = new FriendsPictures();
arrayFriendsPictures = object.arrFriendsPictures;
pictureObject = arrayFriendsPictures.get(0);
if(pictureObject.Image == null){
pictureObject.Image = imageDownloader.download(pictureObject.ImageUrl, (ImageView) holder.icon);
// pictureObject.Image = drawable.fetchDrawableOnThread(pictureObject.ImageUrl, (ImageView) holder.icon);
object.arrFriendsPictures.set(0,pictureObject);
arrFriendsObject.set(position, object);
} else {
holder.icon.setImageBitmap(arrFriendsObject.get(position).arrFriendsPictures.get(0).Image);
}
// holder.icon.setBackgroundResource(R.drawable.photo1);
convertView.setOnClickListener(mShowDetails);
return convertView;
}
class ViewHolder {
TextView text;
ImageView icon;
// ProgressBar showProgress;
}
}
ImageDownloader类:
public class ImageDownloader {
private ProgressDialog dialog;
private static final String LOG_TAG = "ImageDownloader";
public Bitmap download(String url, ImageView imageView) {
resetPurgeTimer();
Bitmap bitmap = getBitmapFromCache(url);
if (bitmap == null) {
bitmap = forceDownload(url, imageView);
} else {
cancelPotentialDownload(url, imageView);
imageView.setImageBitmap(bitmap);
}
return bitmap;
}
private Bitmap forceDownload(String url, ImageView imageView) {
Bitmap bitmap = null;
// State sanity: url is guaranteed to never be null in DownloadedDrawable and cache keys.
if (url == null) {
imageView.setImageDrawable(null);
return null;
}
if (cancelPotentialDownload(url, imageView)) {
BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
imageView.setImageDrawable(downloadedDrawable);
imageView.setMinimumHeight(156);
task.execute(url);
try {
bitmap = task.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return bitmap;
}
private static boolean cancelPotentialDownload(String url, ImageView imageView) {
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
if (bitmapDownloaderTask != null) {
String bitmapUrl = bitmapDownloaderTask.url;
if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
bitmapDownloaderTask.cancel(true);
} else {
// The same URL is already being downloaded.
return false;
}
}
return true;
}
private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
if (imageView != null) {
Drawable drawable = imageView.getDrawable();
if (drawable instanceof DownloadedDrawable) {
DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
return downloadedDrawable.getBitmapDownloaderTask();
}
}
return null;
}
Bitmap downloadBitmap(String url) {
final int IO_BUFFER_SIZE = 4 * 1024;
// AndroidHttpClient is not allowed to be used from the main thread
final HttpClient client = new DefaultHttpClient();
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode +
" while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
// return BitmapFactory.decodeStream(inputStream);
// Bug on slow connections, fixed in future release.
return BitmapFactory.decodeStream(new FlushedInputStream(inputStream));
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (IOException e) {
getRequest.abort();
Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e);
} catch (IllegalStateException e) {
getRequest.abort();
Log.w(LOG_TAG, "Incorrect URL: " + url);
} catch (Exception e) {
getRequest.abort();
Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e);
} finally {
}
return null;
}
static class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int b = read();
if (b < 0) {
break; // we reached EOF
} else {
bytesSkipped = 1; // we read one byte
}
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private String url;
Bitmap bitmap;
private final WeakReference<ImageView> imageViewReference;
public BitmapDownloaderTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
@Override
// can use UI thread here
protected void onPreExecute() {
if(dialog!=null)
{
dialog.setMessage("loading..");
dialog.show();
}
}
@Override
protected Bitmap doInBackground(String... params) {
url = params[0];
return downloadBitmap(url);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if(dialog!=null)
{
dialog.dismiss();
}
addBitmapToCache(url, bitmap);
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
// Change bitmap only if this process is still associated with it
// Or if we don't use any bitmap to task association (NO_DOWNLOADED_DRAWABLE mode)
if ((this == bitmapDownloaderTask)) {
imageView.setImageBitmap(bitmap);
}
}
}
}
static class DownloadedDrawable extends ColorDrawable {
private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;
public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
super(Color.BLACK);
bitmapDownloaderTaskReference =
new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
}
public BitmapDownloaderTask getBitmapDownloaderTask() {
return bitmapDownloaderTaskReference.get();
}
}
private static final int HARD_CACHE_CAPACITY = 10;
private static final int DELAY_BEFORE_PURGE = 10 * 1000; // in milliseconds
// Hard cache, with a fixed maximum capacity and a life duration
private final HashMap<String, Bitmap> sHardBitmapCache =
new LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY / 2, 0.75f, true) {
@Override
protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {
if (size() > HARD_CACHE_CAPACITY) {
// Entries push-out of hard reference cache are transferred to soft reference cache
sSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
return true;
} else
return false;
}
};
// Soft cache for bitmaps kicked out of hard cache
private final static ConcurrentHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache =
new ConcurrentHashMap<String, SoftReference<Bitmap>>(HARD_CACHE_CAPACITY / 2);
private final Handler purgeHandler = new Handler();
private final Runnable purger = new Runnable() {
public void run() {
clearCache();
}
};
private void addBitmapToCache(String url, Bitmap bitmap) {
if (bitmap != null) {
synchronized (sHardBitmapCache) {
sHardBitmapCache.put(url, bitmap);
}
}
}
private Bitmap getBitmapFromCache(String url) {
// First try the hard reference cache
synchronized (sHardBitmapCache) {
final Bitmap bitmap = sHardBitmapCache.get(url);
if (bitmap != null) {
// Bitmap found in hard cache
// Move element to first position, so that it is removed last
sHardBitmapCache.remove(url);
sHardBitmapCache.put(url, bitmap);
return bitmap;
}
}
// Then try the soft reference cache
SoftReference<Bitmap> bitmapReference = sSoftBitmapCache.get(url);
if (bitmapReference != null) {
final Bitmap bitmap = bitmapReference.get();
if (bitmap != null) {
// Bitmap found in soft cache
return bitmap;
} else {
// Soft reference has been Garbage Collected
sSoftBitmapCache.remove(url);
}
}
return null;
}
public void clearCache() {
sHardBitmapCache.clear();
sSoftBitmapCache.clear();
}
private void resetPurgeTimer() {
purgeHandler.removeCallbacks(purger);
purgeHandler.postDelayed(purger, DELAY_BEFORE_PURGE);
}
}
答案 0 :(得分:0)
我正在调用AsyncTask来加载图像而AFAIK异步任务在UI线程上运行,我发现使用线程从Adapter类加载图像的解决方案,我在listview中引用了一个用于加载惰性列表的链接,here是链接。在两个活动之间显示黑屏的主要原因是阻止UI线程。
我并不是说AsyncTask是问题,但我无法正确处理它以加载图像。