Android列表视图更新

时间:2012-03-15 23:54:02

标签: android listview simplecursoradapter lazylist

我正在努力使用数据库中的数据更新列表视图,这可以通过使用SimpleCursorAdapter很好地工作。但是行上的图像视图在活动开始时没有更新,我必须滚动列表几次,然后才在图像视图中加载图像。

这是我用于SimpleCursorAdapter的活页夹:

 private class PromotionViewBinder implements SimpleCursorAdapter.ViewBinder {
            private int done;
            public boolean setViewValue(View view, Cursor cursor, int index) {
                Log.e(""+cursor.getCount(),"");
                View tmpview = view;

                 if (index == cursor.getColumnIndex(PromotionsTable.SEEN_COL)) {
                     boolean read = cursor.getInt(index) > 0 ? true : false;
                     TextView title = (TextView) tmpview;
                     if (!read) {
                         title.setTypeface(Typeface.DEFAULT_BOLD, 0);
                     } else {
                         title.setTypeface(Typeface.DEFAULT);
                     }
                     return true;
                 }  else if (tmpview.getId() == R.id.promotions_list_row_image){
                        String imageURL = cursor.getString(index);
                        Log.e("",imageURL);
                        imageRetriever.displayImage(imageURL, (ImageView)tmpview);
                        return true;
                } else {
                     return false;
                 }
             }
         }

图像检索器类是LazyList example from here。正如您将看到的那样,这是使用runnable来检索图像,一旦完成任务就会自动更新给定的imageView ...您是否认为在途中某处对imageView的引用会丢失?

Thanx提前, 尼克

package com.tipgain.promotions;

图像检索器类:

/**
 * This class is used for retrieving images from a given web link. it uses local
 * storage and memory to store the images. Once a image is downloaded
 * successfully the UI gets updated automatically.
 * 
 * 
 */
public class ImageRetriever {
    private final String TAG = ImageRetriever.class.getName();

    private MemoryImageCache memoryImgCache = new MemoryImageCache();
    private LocalStorageImageCache localFileCache;
    private Map<ImageView, String> imageViewHolders = Collections
            .synchronizedMap(new WeakHashMap<ImageView, String>());
    private ExecutorService execService;
    final int defaultImageID = R.drawable.photo_not_available;

    public ImageRetriever(Context context) {
        localFileCache = new LocalStorageImageCache(context);
        execService = Executors.newFixedThreadPool(5);
    }

    public void displayImage(String url, ImageView imageView) {
        imageViewHolders.put(imageView, url);
        Bitmap bmp = memoryImgCache.retrieve(url);

        if (bmp != null) {
            Log.e("case 1", " " + (bmp != null));
            imageView.setImageBitmap(bmp);

        } else {
            Log.e("case 2", " " + (bmp == null));
            addImageToQueue(url, imageView);
            imageView.setImageResource(defaultImageID);
        }
    }

    private void addImageToQueue(String url, ImageView imageView) {
        NextImageToLoad img = new NextImageToLoad(url, imageView);
        execService.submit(new ImagesRetriever(img));
    }

    /**
     * This method is used for retrieving the Bitmap Image.
     * 
     * @param url
     *            String representing the url pointing to the image.
     * @return Bitmap representing the image
     */
    private Bitmap getBitmap(String url) {
        File imageFile = localFileCache.getFile(url);

        // trying to get the bitmap from the local storage first
        Bitmap bmp = decodeImageFile(imageFile);
        if (bmp != null)
            return bmp;

        // if the file was not found locally we retrieve it from the web
        try {
            URL imageUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) imageUrl
                    .openConnection();
             conn.setConnectTimeout(30000);
             conn.setReadTimeout(30000);
            conn.setInstanceFollowRedirects(true);
            InputStream is = conn.getInputStream();
            OutputStream os = new FileOutputStream(imageFile);
            Utils.CopyStream(is, os);
            os.close();
            bmp = decodeImageFile(imageFile);
            return bmp;
        } catch (MalformedURLException e) {
            Log.e(TAG, e.getMessage());
        } catch (FileNotFoundException e) {
            Log.e(TAG, e.getMessage());
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
        }
        return null;
    }

    /**
     * This method is used for decoding a given image file. Also, to reduce
     * memory, the image is also scaled.
     * 
     * @param imageFile
     * @return
     */
    private Bitmap decodeImageFile(File imageFile) {
        try {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(imageFile), null,
                    options);

            // Find the correct scale value. It should be the power of 2.
            // Deciding the perfect scaling value. (^2).
            final int REQUIRED_SIZE = 100;
            int tmpWidth = options.outWidth, tmpHeight = options.outHeight;
            int scale = 1;
            while (true) {
                if (tmpWidth / 2 < REQUIRED_SIZE
                        || tmpHeight / 2 < REQUIRED_SIZE)
                    break;
                tmpWidth /= 2;
                tmpHeight /= 2;
                scale *= 2;
            }

            // decoding using inSampleSize
            BitmapFactory.Options option2 = new BitmapFactory.Options();
            option2.inSampleSize = scale;
            return BitmapFactory.decodeStream(new FileInputStream(imageFile),
                    null, option2);
        } catch (FileNotFoundException e) {
            Log.e(TAG, e.getLocalizedMessage());
        }
        return null;
    }

    private boolean reusedImage(NextImageToLoad image) {
        Context c = image.imageView.getContext();
        c.getContentResolver().notifyChange(PromotionsProvider.CONTENT_URI, null);

        String tag = imageViewHolders.get(image.imageView);
        if ((tag == null) || (!tag.equals(image.url)))
            return true;
        return false;
    }

    /**
     * Clears the Memory and Local cache
     */
    public void clearCache() {
        memoryImgCache.clear();
        localFileCache.clear();
    }

    /**
     * This class implements a runnable that is used for updating the promotions
     * images on the UI
     * 
     * 
     */
    class UIupdater implements Runnable {
        Bitmap bmp;
        NextImageToLoad image;

        public UIupdater(Bitmap bmp, NextImageToLoad image) {
            this.bmp = bmp;
            this.image = image;
            Log.e("", "ui updater");
        }

        public void run() {
            Log.e("ui updater", "ui updater");
            if (reusedImage(image))
                return;
            Log.e("nick", "" + (bmp == null) + "     chberugv");
            if (bmp != null){
                image.imageView.setImageBitmap(bmp);
                Context c = image.imageView.getContext();
                c.getContentResolver().notifyChange(PromotionsProvider.CONTENT_URI, null);

            }else
                image.imageView.setImageResource(defaultImageID);

            }
    }

    private class ImagesRetriever implements Runnable {
        NextImageToLoad image;

        ImagesRetriever(NextImageToLoad image) {
            this.image = image;
        }

        public void run() {
            Log.e("images retirever", " images retriever");
            if (reusedImage(image))
                return;
            Bitmap bmp = getBitmap(image.url);
            memoryImgCache.insert(image.url, bmp);
            if (reusedImage(image))
                return;
            UIupdater uiUpdater = new UIupdater(bmp, image);
            Activity activity = (Activity) image.imageView.getContext();
            activity.runOnUiThread(uiUpdater);
            //Context c = image.imageView.getContext();
            //c.getContentResolver().notifyChange(PromotionsProvider.CONTENT_URI, null);


        }
    }

    /**
     * This class encapsulates the image being downloaded.
     * 
     * @author Nicolae Anca
     * 
     */
    private class NextImageToLoad {
        public String url;
        public ImageView imageView;

        public NextImageToLoad(String u, ImageView i) {
            url = u;
            imageView = i;
        }
    }

}

修改后的Runnable:

class UIupdater implements Runnable {
    Bitmap bmp;
    NextImageToLoad image;

    public UIupdater(Bitmap bmp, NextImageToLoad image) {
        this.bmp = bmp;
        this.image = image;
    }

    public void run() {
        if (reusedImage(image))
            return;
        if (bmp != null){
            image.imageView.setImageBitmap(bmp);
            Context c = image.imageView.getContext();
            c.getContentResolver().notifyChange(PromotionsProvider.CONTENT_URI, null);

        }else
            image.imageView.setImageResource(defaultImageID);

        }
}

3 个答案:

答案 0 :(得分:1)

这是一种有趣的方式来做你正在做的事情。您是否尝试过扩展简单光标适配器?

  1. 您所做的是实现ViewHolder并将您的imageview放入其中。

  2. 然后在ImageRetriever中编写一个监听器,一旦图像准备好并被检索,将会调用该监听器。

  3. 在Viewholder中实现此侦听器。

  4. 您可以在getView()中创建视图,并在BindView()中请求图像。

  5. 加载图片后,列表将自动刷新。

答案 1 :(得分:0)

一种方法是通过在listview上调用notifyDataSetChenged,另一种方法是将适配器作为成员变量,当listview上的某些内容发生更改时,您调用一个将新listadapter分配给成员适配器的函数。这样,您的列表将在重做时重绘。

答案 2 :(得分:0)

我想,你必须使用一些处理程序,在图像加载后调用,这将为列表适配器调用notifyDataSetChanged

相关问题