Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android列表视图更新_Android_Listview_Simplecursoradapter_Lazylist - Fatal编程技术网

Android列表视图更新

Android列表视图更新,android,listview,simplecursoradapter,lazylist,Android,Listview,Simplecursoradapter,Lazylist,我正在努力用数据库中的数据更新列表视图,这通过使用SimpleCorsorAdapter可以很好地工作。但是行上的图像视图在活动开始时没有更新,我必须在列表中滚动几次,然后图像才会加载到图像视图中 这是我用于SimpleCursorAdapter的活页夹: private class PromotionViewBinder implements SimpleCursorAdapter.ViewBinder { private int done;

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

这是我用于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;
                 }
             }
         }
图像检索器类是。正如您将看到的,这是使用runnable来检索图像,一旦任务完成,就会自动更新给定的imageView…您认为对imageView的引用会在途中丢失吗

Thanx提前, 尼克

图像检索器类:

/**
 * 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;
        }
    }

}

一种方法是在listview上调用notifyDataSetChenged,另一种方法是将adapter作为成员变量,当listview上发生变化时,调用一个函数,将新listadapter分配给成员adapter。这样,您的列表将在更改时重新绘制。

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

这是一种有趣的方法。您是否尝试过扩展简单游标适配器

  • 您要做的是实现一个ViewHolder并将imageview放入其中

  • 然后在ImageRetriever中,编写一个监听器,一旦图像准备好并被检索,它将被调用

  • 在Viewholder中实现此侦听器

  • 在getView()中创建视图,并在BindView()中请求图像

  • 图像加载后,列表将自动刷新


  • 但是我应该在哪里调用notifiydatasetChange?。在setViewValue方法中?在数据库更新时,只要看到数据发生更改或UI需要更新,就可以调用NotifyDataSetChange(),因为这将调用适配器和重绘视图。您还可以覆盖notifyDatasetchanged函数以获得更复杂的函数,或者根据需要,您可以发布一些示例来说明如何执行此操作吗?…我尝试了不同的加载方式,但似乎不起作用…奇怪的是,在我滚动几次后,所有图像都正确加载:DSorry,我不能,但我认为您需要对imageRetriever进行一些更改。也许你可以把这个项目的完整部分发布在ImageRetriever类的第一篇文章中。。。谢谢你的帮助!。。谢谢+1,这是一个非常描述性的问题。我找到了一个更简单的方法,但我不确定这是否花费了太多的cpu…..在我所有的可运行程序中,我称为Context c=image.imageView.getContext();c.getContentResolver().notifyChange(PromotionsProvider.CONTENT_URI,null);列表得到更新了吗?…你认为这是一个好的解决方案吗?我在第一篇文章中添加了修改后的runnable类,因此你可以更好地看到我所做的工作…许多感谢此实现变得越来越有趣。这对我来说是件新鲜事至于CPU消耗,我不想发表评论。我将花一些时间来正确理解这一点。你有没有看到任何性能问题?我用来测试的手机有1.5 ghz的cpu,所以我没有看到任何明显的cpu消耗…我只是问,因为每次用户滚动屏幕时都会加载图像。它首先在软缓存中查找,然后在本地存储缓存(SD卡)上查找,如果未找到,则启动另一个线程,下载图像并将其保存在SD卡上……是的,这是imagedownloader的通常工作方式。我想这是最有效的,我在一个应用程序中使用了类似的下载程序,它似乎工作得很好:)所以我认为你很好去!
    /**
     * 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;
            }
        }
    
    }
    
    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);
    
            }
    }