我想要的是当我滚动时,第7个将是这样的:
但是在更改回第7项的3本书之前,它立即显示第1项的3本书。我认为这个问题与listview的回收机制或缓存有关,但我不知道如何解决它。请教我!
这是我的代码:
Adapter.class:
public class MyAdapter extends BaseAdapter {
private Context mContext;
private int[] mResourceId;
private ImageLoader mImageLoader;
private int count = 0;
private ArrayList<MyImageObject> mImageObjects;
public MyAdapter(Context context, int[] resourceId,ArrayList<MyImageObject> imageObjects) {
// TODO Auto-generated constructor stub
mContext = context;
mResourceId = resourceId;
mImageLoader = new ImageLoader(mContext);
mImageObjects = imageObjects;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return mImageObjects.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
convertView = layoutInflater.inflate(R.layout.item_listview, parent, false);
viewHolder = new ViewHolder();
viewHolder.img1 = (ImageView) convertView.findViewById(R.id.imageView1);
viewHolder.img2 = (ImageView) convertView.findViewById(R.id.imageView2);
viewHolder.img3 = (ImageView) convertView.findViewById(R.id.imageView3);
viewHolder.pb1 = (ProgressBar) convertView.findViewById(R.id.progressBar1);
viewHolder.pb2 = (ProgressBar) convertView.findViewById(R.id.progressBar2);
viewHolder.pb3 = (ProgressBar) convertView.findViewById(R.id.progressBar3);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
Log.e("POSITION", ""+ position);
mImageLoader.displayImage(mImageObjects.get(position),viewHolder.img1, viewHolder.img2, viewHolder.img3, viewHolder.pb1, viewHolder.pb2, viewHolder.pb3);
return convertView;
}
ImageLoader.class:
public class ImageLoader {
private Handler mHandler;
private Context mContext;
private ImageCacher mImageCacher = new ImageCacher();
private ExecutorService mExecutorService;
final int stub_int = R.drawable.ic_launcher;
public ImageLoader(Context context) {
// TODO Auto-generated constructor stub
mContext = context;
mImageCacher = new ImageCacher();
mHandler = new Handler();
mExecutorService = Executors.newFixedThreadPool(3);
}
public void displayImage(MyImageObject imageObject,final ImageView img1,final ImageView img2,
final ImageView img3,final ProgressBar pb1,final ProgressBar pb2,final ProgressBar pb3) {
//Set Imageview invisible if there is no book
if(imageObject.getmResourceId2() == 0){
pb2.setVisibility(View.INVISIBLE);
img2.setVisibility(View.INVISIBLE);
}
else{
img2.setVisibility(View.VISIBLE);
}
//Set Imageview invisible if there is no book
if(imageObject.getmResourceId3() == 0){
pb3.setVisibility(View.INVISIBLE);
img3.setVisibility(View.INVISIBLE);
}else{
img3.setVisibility(View.VISIBLE);
}
//Check if image is already in cache or not
Bitmap bitmap1 = mImageCacher.get(imageObject.getmResourceId1());
Bitmap bitmap2 = mImageCacher.get(imageObject.getmResourceId2());
Bitmap bitmap3 = mImageCacher.get(imageObject.getmResourceId3());
//--------------------------------------------------------//
if (bitmap1 != null) {
pb1.setVisibility(View.INVISIBLE);
img1.setImageBitmap(bitmap1);
} else {
queuePhoto(imageObject.getmResourceId1(), img1,pb1);
}
//-------------------------------------------------------//
if (bitmap2 != null) {
pb2.setVisibility(View.INVISIBLE);
img2.setImageBitmap(bitmap2);
} else {
queuePhoto(imageObject.getmResourceId2(), img2,pb2);
}
//-------------------------------------------------------//
if (bitmap3 != null) {
pb3.setVisibility(View.INVISIBLE);
img3.setImageBitmap(bitmap3);
} else {
queuePhoto(imageObject.getmResourceId3(), img3,pb3);
}
}
private void queuePhoto(int resourceId, ImageView imageView,ProgressBar pb) {
PhotoToLoad photoToLoad = new PhotoToLoad(resourceId, imageView,pb);
mExecutorService.submit(new PhotosLoader(photoToLoad));
}
private class PhotoToLoad {
private int mResourceId;
private ImageView mImageView;
private ProgressBar mProgressBar;
private PhotoToLoad(int r, ImageView i,ProgressBar pb) {
mResourceId = r;
mImageView = i;
mProgressBar = pb;
}
}
private class PhotosLoader implements Runnable {
PhotoToLoad photoToLoad;
public PhotosLoader(PhotoToLoad ptl) {
this.photoToLoad = ptl;
}
@Override
public void run() {
try {
Bitmap bmp = scaleImage(photoToLoad.mResourceId);
mImageCacher.put(photoToLoad.mResourceId, bmp);
BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);
mHandler.post(bd);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
private class BitmapDisplayer implements Runnable {
Bitmap bitmap;
PhotoToLoad photoToLoad;
public BitmapDisplayer(Bitmap b, PhotoToLoad p) {
bitmap = b;
photoToLoad = p;
}
@Override
public void run() {
if (bitmap != null) {
photoToLoad.mProgressBar.setVisibility(View.INVISIBLE);
photoToLoad.mImageView.setImageBitmap(bitmap);
} else {
photoToLoad.mImageView.setImageResource(stub_int);
}
}
}
public Bitmap scaleImage(int resId) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(mContext.getResources(), resId, options);
options.inSampleSize = calculateInSampleSize(options, 90, 130);
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), resId, options);
bitmap = Bitmap.createScaledBitmap(bitmap, 70, 90, true);
return bitmap;
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
public void clearCache() {
mImageCacher.clear();
}
}
最后是ImageCacher:
public class ImageCacher {
private static final String TAG = "MemoryCache";
private Map<Integer, Bitmap> cache = Collections
.synchronizedMap(new LinkedHashMap<Integer, Bitmap>(10, 1.5f, true));
private long size = 0;
private long limit = 1000000;
public ImageCacher() {
setLimit(Runtime.getRuntime().maxMemory() / 4);
}
public void setLimit(long new_limit) {
limit = new_limit;
Log.i(TAG, "MemoryCache will use up to " + limit / 1024 / 1024 + "MB");
}
public Bitmap get(int id) {
try {
if (!cache.containsKey(id))
return null;
return cache.get(id);
} catch (NullPointerException e) {
e.printStackTrace();
return null;
}
}
public void put(int id, Bitmap bitmap) {
try {
if (cache.containsKey(id)) {
size -= getSizeInBytes(cache.get(id));
} else {
cache.put(id, bitmap);
size += getSizeInBytes(bitmap);
checkSize();
}
} catch (Throwable e) {
e.printStackTrace();
}
}
private void checkSize() {
//If cache size exceed limit --> remove last item
if (size > limit) {
Iterator<Entry<Integer, Bitmap>> iter = cache.entrySet().iterator();
while (iter.hasNext()) {
Entry<Integer, Bitmap> entry = iter.next();
size -= getSizeInBytes(entry.getValue());
iter.remove();
if (size <= limit)
break;
}
Log.i(TAG, "Clean cache. New size " + cache.size());
}
}
public void clear() {
try {
cache.clear();
size = 0;
} catch (NullPointerException e) {
e.printStackTrace();
}
}
long getSizeInBytes(Bitmap bitmap) {
if (bitmap == null)
return 0;
return bitmap.getRowBytes() * bitmap.getHeight();
}
}
答案 0 :(得分:0)
尝试
public class X {
public void xCall() {
System.out.println("X method called");
}
public void move(){
System.out.println("I'm in parent class");
}
}
public class Y extends X{
public void yCall() {
System.out.println("Y method called");
}
public void move(){
System.out.println("I'm in child class");
}
}
在displayImage方法的开头
编辑1
使用图像加载器和缓存来显示图像资源很重且没用。
您可能应该在适配器中使用 X a = new X();
X b = new Y();
a.move();// runs the method in X class
b.move();//Runs the method in Y class