2012-03-15 13 views
2

リストビューをデータベースからのデータで更新しようとしていますが、これはSimpleCursorAdapterを使ってうまく動作します。しかし、行のイメージビューはアクティビティの開始時には更新されません。リストを数回スクロールしてから、イメージビューにイメージがロードされます。Androidリストビューの更新

これは私が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です。ご覧のとおり、これはイメージを取得するための実行可能ファイルを使用しています。タスクが完了すると、指定されたimageViewが自動的に更新されます。途中でimageViewへの参照が途中で失われたと思いますか?事前に

ありがとう、 ニック

package com.tipgain.promotions; 

イメージレトリバークラス:Runnableを修正

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

} 

:それはリストビューにnotifyDataSetChengedを呼び出すことである行うに

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

     } 
} 
+1

+1、非常に説明的な質問です。 – gkiar

答えて

0

ためnotifyDataSetChangedを呼び出します画像負荷、後に呼び出して、いくつかのハンドラを使用する必要があります。 Simple Cursor Adapterを拡張しようとしましたか?

  1. ViewHolderを実装してイメージビューを配置します。

  2. ImageRetrieverで、イメージの準備と取得が完了した後に呼び出されるListenerを作成します。

  3. このリスナーをビュー所有者に実装します。

  4. getView()でビューを作成し、BindView()でイメージを要求します。

  5. イメージがロードされると、リストは自動的に更新されます。

+0

私は私を行うための簡単な方法を見つけましたが、私はそれがあまりにも多くのCPUの原価計算されているかどうか.....私が持っているランナブルのいずれかで、私は() コンテキストC = image.imageView.getContextと呼ばれることを確認していません; \t \t \t \t c.getContentResolver()notifyChange(PromotionsProvider.CONTENT_URI、NULL)。リストが更新されますか?...これは良い解決策だと思いますか?あなたはより良い私が行っているものを見ることができるように – Nick

+0

私はこの実装は、より多くの面白い – Nick

+0

...、最初の記事で多くの感謝を変更し、実行可能なクラスを追加しました。その私のためのsomethign新しい。 :) CPU消費に関しては、私はむしろコメントしません。私はこれをいつか正しく理解するために過ごすでしょう。どんな種類のパフォーマンス問題がありますか? – Shubhayu

0

片道、そして別のものは、メンバ変数としてのアダプタを持ち、何かの変更があったときですリストビューでは、新しいlistadapterをメンバアダプタに割り当てる関数を呼び出します。あなたのリストは変更時に再描画されます。

+0

しかし、私はnotifiydatasetChange?をsetViewValueメソッドでどこで呼び出すべきですか? – Nick

+0

データベースが更新されたときにデータが変更されたり、UIを更新する必要がある場合は、アダプタと描画のビューを呼び出すため、notifyDatasetChanget()を呼び出します。また、より複雑な関数や必要に応じてnotifyDatasetchanged関数をオーバーライドすることもできます。 – Mayank

0

私は推測、あなたがやっていることを行うための興味深い方法厥リストアダプタ

+0

これを行う方法の例を投稿できますか?...さまざまな方法で試してみましたが、うまくいかないようです...奇妙なことですD – Nick

+0

申し訳ありませんが、私はできませんが、私はあなたの場合のimageRetrieverにカップルの変更を加える必要があると思います。多分あなたはどこかであなたのプロジェクトのこの完全な部分を投稿することができます –

+0

ImageRetrieverクラスの最初の投稿を念頭に...あなたの助けに感謝!おかげ – Nick

関連する問題