2013-12-10 116 views
4

我正在專門研究CardScrollAdapter中的操作,但在將卡發佈到時間線時,在LiveCard情況下也很好。有沒有辦法使用凌空或任何其他網絡庫來加載使用通用Card類的圖像?延遲加載卡上的圖像

回答

1

「有額外的複雜性,目前的XE12 GDK只支持card.addImage(URI)與當地的資源和文件的URI所以除了上述警告,你必須將圖像下載到文件,然後才能將其添加爲卡片圖像。「

看起來像XE16 +現在支持card.addImage(位圖),因此使用文件作爲臨時緩存可能不再需要。

3

雖然你不能用Card(因爲Card管理自己的佈局),你應該能夠使用其他的功能的凌空處理延遲加載的圖像直接使用排的NetworkImageView類。當您創建Card

  1. ,有它最初使用一個佔位符圖像,如果需要的圖像已經不可用(緩存的地方):

    在一個高層次的,你可以使用這樣的方法。跟蹤某個地方的Card的實例(例如,在適配器中)。

  2. 排隊加載圖像的請求。
  3. 檢索完圖像後,將圖像寫入應用程序的緩存目錄,並使用file: URL將其添加到卡中。
  4. 再次致電Card.toView()重新生成卡的視圖並根據需要更新您的用戶界面。
+1

這就是我目前正在實施的。這有點令人失望,因爲它需要爲這些圖像管理文件緩存,而不是在檢索時從內存中加載它們。 – yincrash

+0

@tony - 'Card.toViews()'似乎不存在。你的意思是別的嗎? –

+0

錯字 - 有一個額外的「s」。編輯它到'toView'。 –

1

好的有辦法做到這一點,但它有點複雜。訣竅是,您無法在適配器的getView()中調度異步映像加載任務,這是您通常在android中執行的方式。如果您嘗試,您會發現在準備加載圖像時,由card.toView()返回的ImageView將會GC'd。似乎是GDK中的一個錯誤,或者可能是它設計的方式,我不確定。

當前的XE12 GDK僅支持帶本地資源和文件URI的card.addImage(Uri),這就增加了複雜性。因此,除了上述警告之外,您必須先將圖像下載到文件,然後才能將其添加爲卡片圖像。

我將使用Android Universal Image Loader來協助完成圖像下載任務。下面是這樣做的課程:

public class CardImageLoader { 

    private static final String TAG = CardImageLoader.class.getSimpleName(); 
    private static final boolean DEBUG = false; 

    private static final int MAX_IMAGE_LOAD_RETRIES = 3; 
    private static Map<String, Integer> mLoadFailures = new ConcurrentHashMap<String, Integer>(); 

    public static void init(Context context) { 
     File cacheDir = StorageUtils.getCacheDirectory(context); 
     DisplayImageOptions options = new DisplayImageOptions.Builder() 
       .cacheOnDisc(true) 
       .build(); 
     ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context) 
       .discCache(new UnlimitedDiscCache(cacheDir)) 
       .defaultDisplayImageOptions(options) 
       .build(); 
     ImageLoader.getInstance().init(config); 
    } 

    public static void loadCardImage(final Card card, final String imageUri, final CardScrollView cardScrollView) { 
     card.setImageLayout(Card.ImageLayout.FULL); 
     int failures = mLoadFailures.containsKey(imageUri) ? mLoadFailures.get(imageUri) : 0; 
     if (failures > MAX_IMAGE_LOAD_RETRIES) { 
      if (DEBUG) Log.i(TAG, "Exceeded max retries on imageUri=" + imageUri); 
      return; 
     } 
     File file = ImageLoader.getInstance().getDiscCache().get(imageUri); 
     if (file != null && file.exists() && file.length() > 0) { 
      Uri uri = Uri.fromFile(file); 
      card.addImage(uri); 
     } 
     else { 
      ImageLoader.getInstance().loadImage(imageUri, new ImageLoadingListener() { 
       @Override 
       public void onLoadingStarted(String imageUri, View view) { 
        if (DEBUG) Log.i(TAG, "onLoadingStarted"); 
       } 

       @Override 
       public void onLoadingFailed(String imageUri, View view, FailReason failReason) { 
        if (DEBUG) Log.i(TAG, "onLoadingFailed"); 
        int failures = mLoadFailures.containsKey(imageUri) ? mLoadFailures.get(imageUri) : 0; 
        mLoadFailures.put(imageUri, ++failures); 
       } 

       @Override 
       public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { 
        File file = ImageLoader.getInstance().getDiscCache().get(imageUri); 
        if (DEBUG) Log.i(TAG, "onLoadingComplete uri=" + imageUri + " file=" + file 
          + " len=" + (file == null ? 0 : file.length())); 
        if (file != null && file.exists() && file.length() > 0) { 
         if (DEBUG) Log.i(TAG, "onLoadingComplete scheduling update of scroll views"); 
         if (cardScrollView != null) 
          cardScrollView.updateViews(true); 
        } 
       } 

       @Override 
       public void onLoadingCancelled(String imageUri, View view) { 
        if (DEBUG) Log.i(TAG, "onLoadingCancelled"); 
       } 
      }); 
     } 
    } 
} 

以下是它的工作原理。在適配器的getView()中,我們找到了要加載的URL。我們問圖像加載器是否已經獲取了圖像緩存。如果有,我們會找到本地文件Uri並撥打card.addImage(Uri),我們就完成了。如果我們沒有緩存圖像,我們不能使用正常的圖像加載程序調用以前描述的原因。相反,我們使用loadImage()' and if successful, ask the CardScrollView下載文件重新顯示自己(不要嘗試在此處設置卡,即使使用變量final,也不會發生任何事情)。這將最終導致getView()再次被調用,只有這一次文件將被緩存。因此圖像將被添加到卡上,並且您的卡片將正確顯示。

還有一些失敗的下載跟蹤,以防止在下載失敗時重新顯示循環的CardScrollView

你如何使用它?挺容易。首先在你的onCreate()你需要初始化這條線的圖像加載器:

CardImageLoader.init(this); 

其次,在適配器getView()方法,當你要加載在卡中的圖像調用此方法:

CardImageLoader.loadCardImage(card, url, mCardScrollView); 

然後您將顯示帶有圖像的卡片。目前我發現的唯一警告是,不要一次加載超過20張圖像,否則您可能會出現性能問題。裝載150個墜毀的玻璃,所以要小心。除此之外,它一直很好。

更新:我減慢加載列表與10 +圖像。我不確定這是因爲在每個圖像加載或什麼後調用updateViews()

+0

此代碼適用於我,謝謝!我需要將類方法修改爲不是靜態的,以便爲最新版本的Glass進行編譯。 – MikeN

2

「更新:我得到的影片加載速度超過10張圖片,我不確定這是因爲在每次加載圖片或調用後調用updateViews()。

確保您的CardScrollAdapter getView()方法不會嘗試在每次調用時加載圖像。

例如:

@Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     if (getCards() == null) return null; 

     MyCard card = getCards().get(position); 

     if (! card.isImageLoaded()) { 
        CardImageLoader.loadCardImage(...);  
     } 

      return card.toView(); 

    } 
+0

看起來像最新版本的卡片不再定義addImage(uri) – user1679130