2

データベースのデータでリストビューを更新するのに苦労しています。これは、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の例です。ご覧のとおり、これはランナブルを使用して画像を取得し、タスクが完了すると、指定されたimageViewを自動的に更新します...途中でimageViewへの参照が失われたと思いますか?

よろしくお願いします、ニック

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

}

変更されたランナブル:

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);

        }
}
4

3 に答える 3

1

それはあなたがしていることをするための興味深い方法です。Simple Cursor Adapterを拡張してみましたか?

  1. ViewHolderを実装し、その中にimageviewを配置します。

  2. 次に、ImageRetrieverで、画像の準備ができて取得されると呼び出されるリスナーを記述します。

  3. このリスナーをビューホルダーに実装します。

  4. getView()でビューを作成し、BindView()で画像をリクエストします。

  5. 画像が読み込まれると、リストは自動的に更新されます。

于 2012-03-16T02:05:17.720 に答える
0

これを行う1つの方法は、listviewでnotifyDataSetChengedを呼び出すことです。別の方法は、メンバー変数としてアダプターを使用し、listviewで何かが変更されたときに、新しいlistadapterをメンバーアダプターに割り当てる関数を呼び出すことです。そうすれば、変更時にリストが再描画されます。

于 2012-03-16T00:02:10.133 に答える
0

おそらく、画像の読み込み後に呼び出すハンドラーを使用する必要があります。これによりnotifyDataSetChanged、リストアダプターが呼び出されます。

于 2012-03-16T00:38:03.827 に答える