Tôi có một bộ điều hợp tùy chỉnh mở rộng ArrayAdapter, nó thực hiện các mẫu khung nhìn để hiển thị dữ liệu (văn bản + hình ảnh) từ một dịch vụ web.Android: hiển thị ListView hình ảnh nhấp nháy khi thêm dữ liệu vào ArrayAdapter
để tải lười biếng trong những hình ảnh tôi sử dụng mô hình nhiệm vụ async từ công tác đào tạo tiên tiến trong trang web của nhà phát triển của Android,
tôi cũng sử dụng đĩa + ram bitmap cache.
khi có dữ liệu bổ sung cần truy xuất, tôi thêm chế độ xem chân trang để nhấp vào nó sẽ truy xuất dữ liệu bổ sung từ dịch vụ web và thêm dữ liệu đó vào bộ điều hợp.
vấn đề là khi dữ liệu mới này được thêm vào, một số hình ảnh hiển thị đang thay đổi và ngay lập tức thay đổi trở lại, dẫn đến nhấp nháy lạ.
ngoài việc mọi thứ hoạt động tốt và việc cuộn trơn tru.
theo như tôi hiểu những thay đổi hình ảnh đó đang xảy ra khi chế độ xem hiển thị đang được làm mới khi dữ liệu mới được thêm vào.
có cách nào bỏ qua hành vi không mong muốn này không?
này là lớp làm tải và quản lý các nhiệm vụ async
public class ImageDownloader {
private ImageCache mCache;
private int reqWidth;
private int reqHeight;
public void download(String url, ImageView imageView, ImageCache imageCache, int reqHeight, int reqWidth) {
mCache = imageCache;
this.reqHeight = reqHeight;
this.reqWidth = reqWidth;
if (cancelPotentialDownload(url, imageView)) {
BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
imageView.setImageDrawable(downloadedDrawable);
task.execute(url);
}
}
private class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private String url;
private WeakReference<ImageView> imageViewReference;
public BitmapDownloaderTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
@Override
protected Bitmap doInBackground(String... strings) {
Bitmap bitmap = null;
try {
bitmap = mCache.getBitmapFromURL(strings[0], reqWidth, reqHeight);
} catch (IOException e) {
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) bitmap = null;
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
private static class DownloadedDrawable extends ColorDrawable {
private WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;
public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
}
public BitmapDownloaderTask getBitmapDownloaderTask() {
return bitmapDownloaderTaskReference.get();
}
}
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;
}
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 {
return false;
}
}
return true;
}
}
đây là adapter:
lớp tin PlaceAdapter kéo dài ArrayAdapter { thức int viewResourceId;
public PlaceAdapter(Context context, int textViewResourceId, List<PlaceModel> objects) {
super(context, textViewResourceId, objects);
viewResourceId = textViewResourceId;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = getLayoutInflater();
convertView = inflater.inflate(viewResourceId, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
PlaceModel place = getItem(position);
holder.name.setText(place.getName());
holder.address.setText(place.getVicinity());
holder.position = position;
if (place.getIcon() != null) {
String url = mImageViewUrls.get(holder.image);
if (url == null || (url != null && !url.equals(place.getIcon()))) {
mDownloader.download(place.getIcon(), holder.image, mCache, 100, 100);
mImageViewUrls.put(holder.image, place.getIcon());
}
} else {
holder.image.setImageBitmap(null);
mImageViewUrls.remove(holder.image);
}
return convertView;
}
}
private class ViewHolder {
public final ImageView image;
public final TextView name;
public final TextView address;
public int position;
public ViewHolder(View row) {
image = (ImageView) row.findViewById(R.id.placeRow_imageView);
name = (TextView) row.findViewById(R.id.placeRow_placeName);
address = (TextView) row.findViewById(R.id.placeRow_placeAddress);
}
}
mImageViewUrls
là một WeakHashMap<ImageView, String>
mà các bản đồ giữa một ImageView
và một url, vì vậy không cần thiết nhiệm vụ async invocations có thể giảm bằng cách kiểm tra nếu ImageView
đã cho thấy hình ảnh theo yêu cầu. mà không thực hiện điều này, nhấp nháy đang xảy ra trong tất cả các hình ảnh hiển thị về thay đổi dữ liệu. với điều này, nó chỉ xảy ra với một số hình ảnh. EDIT: Tôi đã cố gắng để loại bỏ hoàn toàn nguyên nhân của vấn đề này, trước tiên tôi đã cố gắng hoàn toàn bỏ qua việc thực hiện bộ nhớ cache và tải xuống từng bitmap từ mạng, sau đó tôi thử gói bộ điều hợp với bộ điều hợp Endless của CommonsWare và cả hai kết quả .. vì vậy điều này chỉ để lại lớp ImageDownloader và bộ điều hợp của tôi là nguyên nhân có thể .. Tôi hoàn toàn bị mất về điều này.